I have a Windows DLL that exposes a function. Let's call it Fn. It takes two CStrings as parameters and returns a CString:
CString Fn(CString a, CString b)
The C++ code you see below successfully loads the DLL and invokes Fn. A side effect of Fn is that it prints the value of parameter a to stdtout. So I see:
Parameter a has value "A"
However, when I do the same from Python, I get:
Parameter a has value "B"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OSError: exception: access violation reading 0x00000005
So Fn somehow receives parameter b instead of parameter a.
My question is: Why do my function parameters get mangled when calling the DLL from Python, but not from C++?
In fact, this problem does not only occur when I call Fn from Python, but also when I call it from NSIS via:
System::Call "My::Fn(m 'A', m 'B') m .r0"
I thought that it might be a problem with the calling convention. So I changed windll.LoadLibrary to cdll.LoadLibrary. Unfortunately, this produces the exact same output.
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")
#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;
}
Using the comments to my question, I managed to find a solution.
The problem seems to have been that CString is an MFC concept that neither Python nor NSIS know about. Changing Fn's signature to
LPCTSTR Fn(LPCTSTR, LPCTSTR)
solved the issue.
User contributions licensed under CC BY-SA 3.0