从 Python 调用 Windows DLL 函数时出错
Error invoking Windows DLL function from Python
我有一个公开函数的 Windows DLL。我们称它为 Fn
。它需要两个 CStrings
作为参数和 returns 一个 CString
:
CString Fn(CString a, CString b)
您在下面看到的 C++ 代码成功加载了 DLL 并调用了 Fn
。 Fn
的一个副作用是它将参数 a
的值打印到 stdtout。所以我看到:
Parameter a has value "A"
但是,当我从 Python 执行相同操作时,我得到:
Parameter a has value "B"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OSError: exception: access violation reading 0x00000005
所以 Fn
以某种方式接收参数 b
而不是参数 a
.
我的问题是:为什么我的函数参数在从 Python 而不是从 C++ 调用 DLL 时会被破坏?
其实这个问题不仅出现在我从Python调用Fn
的时候,当我从NSIS调用的时候也会出现这个问题:
System::Call "My::Fn(m 'A', m 'B') m .r0"
我认为这可能是调用约定的问题。所以我把windll.LoadLibrary
改成了cdll.LoadLibrary
。不幸的是,这会产生完全相同的输出。
Python 代码(无效)
from ctypes import *
f = windll.LoadLibrary('My.dll').Fn
f.argtypes = [c_char_p, c_char_p]
f.restype = c_char_p
f(b"A", b"B")
C++ 代码(有效)
#include <atlstr.h>
typedef CString (*Fn)(CString, CString);
int main( void ) {
HINSTANCE dll = LoadLibrary("My.dll");
Fn f = (Fn) GetProcAddress(dll, "Fn");
f("A", "B");
FreeLibrary(dll);
return 0;
}
根据对我的问题的评论,我设法找到了解决方案。
问题似乎是 CString
是一个 MFC 概念,Python 和 NSIS 都不知道。将 Fn
的签名更改为
LPCTSTR Fn(LPCTSTR, LPCTSTR)
解决了问题。
我有一个公开函数的 Windows DLL。我们称它为 Fn
。它需要两个 CStrings
作为参数和 returns 一个 CString
:
CString Fn(CString a, CString b)
您在下面看到的 C++ 代码成功加载了 DLL 并调用了 Fn
。 Fn
的一个副作用是它将参数 a
的值打印到 stdtout。所以我看到:
Parameter a has value "A"
但是,当我从 Python 执行相同操作时,我得到:
Parameter a has value "B"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OSError: exception: access violation reading 0x00000005
所以 Fn
以某种方式接收参数 b
而不是参数 a
.
我的问题是:为什么我的函数参数在从 Python 而不是从 C++ 调用 DLL 时会被破坏?
其实这个问题不仅出现在我从Python调用Fn
的时候,当我从NSIS调用的时候也会出现这个问题:
System::Call "My::Fn(m 'A', m 'B') m .r0"
我认为这可能是调用约定的问题。所以我把windll.LoadLibrary
改成了cdll.LoadLibrary
。不幸的是,这会产生完全相同的输出。
Python 代码(无效)
from ctypes import *
f = windll.LoadLibrary('My.dll').Fn
f.argtypes = [c_char_p, c_char_p]
f.restype = c_char_p
f(b"A", b"B")
C++ 代码(有效)
#include <atlstr.h>
typedef CString (*Fn)(CString, CString);
int main( void ) {
HINSTANCE dll = LoadLibrary("My.dll");
Fn f = (Fn) GetProcAddress(dll, "Fn");
f("A", "B");
FreeLibrary(dll);
return 0;
}
根据对我的问题的评论,我设法找到了解决方案。
问题似乎是 CString
是一个 MFC 概念,Python 和 NSIS 都不知道。将 Fn
的签名更改为
LPCTSTR Fn(LPCTSTR, LPCTSTR)
解决了问题。