Python ctypes加载dll库时不会出错,但在函数调用时不会返回预期结果
我试图在反病毒供应商的serverapi.dll周围编写一个Python 3.8.2包装器,这会让我的手变得脏兮兮的。它们提供了一些C代码片段,展示了如何在C/C++中使用它,我正在尝试将这些代码改编成Python C类型。我无法控制DLL——我只能加载它并尝试调用函数。我已经将他们的代码粘贴到VisualStudio中,对其进行编译,然后看着它按照他们的说法返回 我要修改的供应商代码:Python ctypes加载dll库时不会出错,但在函数调用时不会返回预期结果,python,windows,ctypes,Python,Windows,Ctypes,我试图在反病毒供应商的serverapi.dll周围编写一个Python 3.8.2包装器,这会让我的手变得脏兮兮的。它们提供了一些C代码片段,展示了如何在C/C++中使用它,我正在尝试将这些代码改编成Python C类型。我无法控制DLL——我只能加载它并尝试调用函数。我已经将他们的代码粘贴到VisualStudio中,对其进行编译,然后看着它按照他们的说法返回 我要修改的供应商代码: HMODULE hMod = LoadLibrary(L"ServerApi.dll")
HMODULE hMod = LoadLibrary(L"ServerApi.dll");
if (!hMod)
{
std::cout << "Cannot load library error. Last error is:" << GetLastError() << std::endl;
return 1;
}
era_init_lib init_lib = (era_init_lib)GetProcAddress(hMod, "era_init_lib");
if (!init_lib)
{
std::cout << "Cannot init library" << std::endl;
FreeLibrary(hMod);
return 1;
}
...
int res = init_lib();
if (res)
{
std::cout << "Init lib result:" << res << std::endl;
FreeLibrary(hMod);
return 1;
}
我的肾盂尝试:
from ctypes import *
serverapi = WinDLL('../lib/ServerApi.dll')
era_init = serverapi.era_init_lib
era_init.restype = c_int
era_init.argtypes = None
res = era_init()
print("init code: " + str(res)) // prints "init code: 2"
我尝试的问题是,它运行时没有Python错误,但返回代码错误。当我编译上面的C代码时,era_init_lib()会返回它应该返回的0,并且库已经准备好使用了。当我运行python代码时,它运行的代码是2。根据本模块的稀疏文档,可能的返回代码为:
Return value:
ERA_SUCCESS 0
ERA_INVALID_ARGUMENT 1
ERA_NOT_INITIALIZED 3
列表中可疑地缺少了2,这使我相信Python错误地加载了这个库
我尝试过的事情:
- 我认为这是一个Windows调用约定DLL,但我尝试用CDLL加载它。没有更改,没有python错误/堆栈跟踪/相同的返回代码
- 我已经验证了DLL是x64,我的Python解释器是x64
- 我让procmon在python代码执行时运行。它似乎像我初步理解的那样加载了所有依赖DLL
- 我试图包装C代码用来加载它的函数。没有用,但尝试如下:
- 我尝试了以下功能的原型,但没有成功:
有人知道下一步要去哪里吗?在x64中只有一个调用约定
windle
和CDLL
是相同的。你的方法没有错。procmon是否显示加载了相同的DLL,pathwise?很高兴知道!有点像是在ProcMon前线。VisualStudio在程序执行时按顺序提供DLL加载列表。我对照ProcMon检查了这个列表,看起来这个列表有问题。Python代码在尝试serverapi.dll之前加载ws2_32.dll。C代码首先加载serverapi.dll,然后加载ws2_32.dll。深入研究ProcMon,我检查了它的日志末尾,C代码中加载的所有内容都已加载并附加到python.exe进程。这两种语言中的路径总是相同的——对于大多数语言,都是C:\windows\system32them@MarkTolonen在你问起ProcMon之后,我仔细查看了结果。我注意到serverapi.dll依赖于一个network.dll,它只能查看C:\Python\Python38\network.dll。它不会搜索系统路径或项目位置。出于好奇,我把network.dll放在上面的路径上,一切正常!现在的问题是如何让它正确地搜索路径,以便与其他项目文件一起找到它。欢迎使用DLL地狱:)我想知道为什么Python38目录中有network.DLL。我的安装没有。x64中只有一个调用约定windl
和CDLL
是相同的。你的方法没有错。procmon是否显示加载了相同的DLL,pathwise?很高兴知道!有点像是在ProcMon前线。VisualStudio在程序执行时按顺序提供DLL加载列表。我对照ProcMon检查了这个列表,看起来这个列表有问题。Python代码在尝试serverapi.dll之前加载ws2_32.dll。C代码首先加载serverapi.dll,然后加载ws2_32.dll。深入研究ProcMon,我检查了它的日志末尾,C代码中加载的所有内容都已加载并附加到python.exe进程。这两种语言中的路径总是相同的——对于大多数语言,都是C:\windows\system32them@MarkTolonen在你问起ProcMon之后,我仔细查看了结果。我注意到serverapi.dll依赖于一个network.dll,它只能查看C:\Python\Python38\network.dll。它不会搜索系统路径或项目位置。出于好奇,我把network.dll放在上面的路径上,一切正常!现在的问题是如何让它正确地搜索路径,以便与其他项目文件一起找到它。欢迎使用DLL地狱:)我想知道为什么Python38目录中有network.DLL。我的安装没有它。
Return value:
ERA_SUCCESS 0
ERA_INVALID_ARGUMENT 1
ERA_NOT_INITIALIZED 3
from ctypes import *
from ctypes import wintypes
windll.kernel32.GetProcAddress.argtypes = [wintypes.HMODULE, wintypes.LPCSTR]
windll.kernel32.GetProcAddress.restype = WINFUNCTYPE(c_int)
init_lib = windll.kernel32.GetProcAddress(wdll, "era_init_lib".encode("cp1252"));
init_lib.restype = c_int
print(str(init_lib())) // Prints "2"
era_init_proto = WINFUNCTYPE(c_int)
era_init = era_init_proto(("era_init_lib", serverapi), None)