Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
799 views
in Technique[技术] by (71.8m points)

c++ - ctypes.ArgumentError when calling DLL functions with Python

I'm using ctypes to call functions in a DLL file according to a description file that describe the DLL functions' parameters and returns. Here is one function in this DLL called InitNetwork. Below is its description:

Function:BOOL InitNetwork(char  LocalIP[],char  ServerIP[],int  LocalDeviceID);
Arguments:LocalIP
           ServerIP
           LocalDeviceID
Return:Success:TRUE;
        Faile:FALSE;

What I'm doing in Python is like this:

from ctypes import *
import os

#Load Dll:
cppdll = CDLL("C:\VS_projects\MusicServer_Flask\NetServerInterface.dll")

#Get the function:
initnetwork = getattr(cppdll, "?InitNetwork@@YAHQAD0H@Z")  # The function can be successfully accessed.

#specify arguments' types:
initnetwork.argtypes = [c_char_p,c_char_p,c_int]

After this, I try:

initnetwork("192.168.1.103", "192.168.1.103", 1111)

Get an Error:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ctypes.ArgumentError: argument 1: <class 'TypeError'>: wrong type

If I try this:

initnetwork(LocalIP = "192.168.1.103", ServerIP = "192.168.1.103", LocalDeviceID = 1111)

I will get:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: this function takes at least 3 arguments (0 given)

Why these errors comes out? How can I call this function successfully? Any suggestion is appreciated. Thank you for your attention!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

ctypes official doc: [Python 3.5]: ctypes - A foreign function library for Python.

Created a dummy .dll to mimic your behavior.

dll.c:

#include <stdio.h>
#include <Windows.h>


__declspec(dllexport) BOOL InitNetwork(char LocalIP[], char ServerIP[], int LocalDeviceID) {
    printf("From C:
LocalIP: [%s]
ServerIP: [%s]
LocalDeviceID: %d
", LocalIP, ServerIP, LocalDeviceID);
    return TRUE;
}

Check [SO]: How to compile a 64-bit dll written in C? (@CristiFati's answer) for details how to build it (took the exact same steps, command in this case was: cl /nologo /LD /DWIN64 /DWIN32 /Tp dll.c /link /OUT:NetServerInterface.dll).

The (main) problem is that in Python3, char* no longer maps to a string, but to a bytes object.

code.py:

import sys
import ctypes
from ctypes import wintypes


FILE_NAME = "NetServerInterface.dll"
FUNC_NAME = "?InitNetwork@@YAHQEAD0H@Z"  # Name different than yours: if func was declared as `extern "C"`, the "normal" name would be required


def main():
    net_server_interface_dll = ctypes.CDLL(FILE_NAME)
    init_network = getattr(net_server_interface_dll, FUNC_NAME)

    init_network.argtypes = [ctypes.c_char_p, ctypes.c_char_p, ctypes.c_int]
    init_network.restype = wintypes.BOOL

    init_network(b"192.168.1.103", b"192.168.1.103", 1111)


if __name__ == "__main__":
    print("Python {:s} on {:s}
".format(sys.version, sys.platform))
    main()

Output:

(py35x64_test) e:WorkDevStackOverflowq050325050>"e:WorkDevVEnvspy35x64_testScriptspython.exe" code.py
Python 3.5.4 (v3.5.4:3f56838, Aug  8 2017, 02:17:05) [MSC v.1900 64 bit (AMD64)] on win32

From C:
        LocalIP: [192.168.1.103]
        ServerIP: [192.168.1.103]
        LocalDeviceID: 1111

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...