我正在使用ctypes根据描述DLL函数参数和返回的描述文件调用DLL文件中的函数。这个DLL中有一个名为InitNetwork的函数。以下是其描述:
EmptyUserNamePassword()
我在Python中所做的是这样的:
Function:BOOL InitNetwork(char LocalIP[],char ServerIP[],int LocalDeviceID);
Arguments:LocalIP
ServerIP
LocalDeviceID
Return:Success:TRUE;
Faile:FALSE;
在此之后,我尝试:
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]
收到错误:
initnetwork("192.168.1.103", "192.168.1.103", 1111)
如果我试试这个:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ctypes.ArgumentError: argument 1: <class 'TypeError'>: wrong type
我会得到:
initnetwork(LocalIP = "192.168.1.103", ServerIP = "192.168.1.103", LocalDeviceID = 1111)
为什么会出现这些错误?如何成功调用此函数?任何建议表示赞赏。谢谢你的关注!
答案 0 :(得分:2)
ctypes 官方文档:[Python 3.5]: ctypes - A foreign function library for Python。
创建一个虚拟的 .dll 来模仿你的行为。
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;
}
检查[SO]: How to compile a 64-bit dll written in C? (@CristiFati's answer)以获取有关如何构建它的详细信息(采取完全相同的步骤,在这种情况下命令为:cl /nologo /LD /DWIN64 /DWIN32 /Tp dll.c /link /OUT:NetServerInterface.dll
)。
(主要)问题是在 Python3 中,char*
不再映射到字符串,而是映射到字节对象
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()
<强>输出强>:
(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
答案 1 :(得分:1)
我认为问题出在您的C ++界面中。我想如果你把它改成Function:BOOL InitNetwork(char * LocalIP,char * ServerIP,int LocalDeviceID);
你的第一个电话(没有关键字)应该有效,但我认为你可能需要删除最后一个参数的引号(毕竟它是一个int)。