从Python调用Windows DLL函数时出错

时间:2019-10-03 15:13:26

标签: python c++ windows dll ctypes

我有一个公开功能的Windows DLL。我们称之为Fn。它以两个CStrings作为参数,并返回一个CString

CString Fn(CString a, CString b)

您在下面看到的C ++代码成功加载了DLL并调用了FnFn的副作用是它将参数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;
}

1 个答案:

答案 0 :(得分:0)

使用对我的问题的评论,我设法找到了解决方案。

问题似乎是Fn是MFC概念,Python和NSIS都不知道。将LPCTSTR Fn(LPCTSTR, LPCTSTR) 的签名更改为

select * from MyTable
where cast(substring(p_no,4,4) as int) > serial_no

解决了这个问题。