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!
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:\n\tLocalIP: [%s]\n\tServerIP: [%s]\n\tLocalDeviceID: %d\n", 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}\n".format(sys.version, sys.platform))
main()
Output:
(py35x64_test) e:\Work\Dev\StackOverflow\q050325050>"e:\Work\Dev\VEnvs\py35x64_test\Scripts\python.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
I think the problem is in your C++ interface. I think if you change it to Function:BOOL InitNetwork(char * LocalIP,char * ServerIP,int LocalDeviceID);
your first call (without the keywords) should work but I think you might need to remove the quotes around the last argument (it is an int after all).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With