Ошибка вызова функции Windows DLL из Python - PullRequest
0 голосов
/ 03 октября 2019

У меня есть Windows DLL, которая предоставляет функцию. Давайте назовем это Fn. Он принимает два CStrings в качестве параметров и возвращает 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.

Мой вопрос: почему параметры моей функции искажаются при вызове DLL из Python, а не из C ++?

На самом деле, эта проблема непроисходят только когда я вызываю Fn из Python, но также когда я звоню из 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 голосов
/ 07 октября 2019

Используя комментарии к моему вопросу, мне удалось найти решение.

Проблема, похоже, заключалась в том, что CString - это концепция MFC, о которой не знают ни Python, ни NSIS. Изменение подписи Fn на

LPCTSTR Fn(LPCTSTR, LPCTSTR)

решило проблему.

...