Как я могу скомпилировать несколько файлов C ++, чтобы использовать их с Python ctypes? - PullRequest
1 голос
/ 12 февраля 2020

У меня небольшая проблема с компиляцией нескольких C ++ на Windows. Я реализовал четыре класса в C ++ для криптографии с помощью gmp. Я хочу позвонить им из Python с помощью ctypes. Я написал файл cpp с ключевым словом extern:

#include "integer.h"
#include "modular_number.h"
#include "padic_number.h"
#include "rational_number.h"

extern "C" {
    __declspec(dllexport) ModNum* newModNum(const char * n, const char * p) { return new ModNum(Integer(n), Integer(p)); }
    __declspec(dllexport) const char* getModValue(const ModNum& mod){ return mod.getValue().getValue(); }

    __declspec(dllexport) RationalNum* newRationalNum(const char* mpq) { return new RationalNum(mpq); }
    __declspec(dllexport) const char* getRationalValue(const RationalNum& rat){ return rat.getValue(); }

    __declspec(dllexport) PadicNum* newPadicNum(const char* n, const char* base) { return new PadicNum(Integer(n), Integer(base)); }
    __declspec(dllexport) const char* getPadicValue(const PadicNum& padic){ return padic.getValue().getValue(); }
}

Мои файлы были скомпилированы с:

mingw32-g++ -fexceptions -g -fexpensive-optimizations -flto -O3 -Weffc++ -Wextra -Wall -std=c++14 -fPIC -Og -IC:\MinGW\include -flto -s -lgmp -lmpfr -lpthread -c -fPIC *.cpp -I"C:\Program Files\Python38-32\include" -I"C:\Program Files\Python38-32\libs"

mingw32-g++.exe -shared -Wl,-dll -o numeric.dll *.o -lgmp -lmpfr -lgmpxx -static

Но когда я использую эти команды в Python:

import ctypes;
x = ctypes.DLL("./numeric.dll");

Переменная x не имеет функций: newModNum, getModValue, et c ... Может кто-нибудь сказать мне, что я делаю неправильно? Я не получаю ошибки, и я не понимаю. Другие мои файлы - это обычные C ++ файлы с заголовком и реализацией.

Заранее спасибо и хорошего дня!

1 Ответ

1 голос
/ 13 февраля 2020

ctypes функции импортируются при первом использовании. Используя libc в качестве примера:

>>> import ctypes
>>> libc = ctypes.CDLL("libc.so.06")
>>> "printf" in dir(libc)
False
>>> libc.printf
<_FuncPtr object at 0x7f6512c23430>
>>> "printf" in dir(libc)
True

ctypes предполагает, что все параметры и возвращаемое значение равны int. Вы должны дать подсказки типа, которые также удобно импортировать функции.

import ctypes
x = ctypes.DLL("./numeric.dll")
x.newModNum.argtypes = [ctypes.c_char_p, ctypes.c_char_p] # <-- also imports
x.newModNum.rettype = ctypes.c_void_p

И удалить точки с запятой в конце строк. Это вызывает опасные скачки артериального давления у python программистов.

...