То, как вы структурировали свой код C , выглядит ближе к модулю расширения ( [Python 3]: расширение Python с помощью C или C ++ ), а непростой .dll .Проверьте [SO]: передать str как массив int в расширенную функцию Python C (расширенную с помощью SWIG) (ответ @ CristiFati) для сравнения методов.
Затем, как примечаниевам необходимо указать argtypes и restype для импортируемой функции (именно по этой причине вы получаете int ).Проверьте [SO]: Python ctypes cdll.LoadLibrary, создать экземпляр объекта, выполнить его метод, адрес частной переменной усекается , что может случиться, если вы этого не сделаете.
Также перечисляет [Python 3]: ctypes - библиотека сторонних функций для страницы Python .
Несколько замечаний о коде:
- Поскольку вы используете Python C API функций в вашем .dll , вы должны вызывать его через
ctypes.PyDLL
(ctypes.pydll.LoadLibrary
) - Поскольку вы возвращаете
PyObject*
, на Python сторона, которую вы должны использовать py_object (отметьте [SO]: как привести указатель ctypes к экземпляру класса Python для получения более подробной информации)
Итак, при условии, что у вас есть работающий .dll , вот как бы вы его использовали (публикуя код вслепую):
mylib = ctypes.pydll.LoadLibrary('./mylib.so')
outvar = ctypes.py_object.in_dll(mylib, "outvar") # Note that you might have to declare it as extern "C", so its name doesn't get mangled
@ EDIT0 :
Я создал фиктивный пример, чтобы проверить, все ли работает.
dll.c :
#include <Python.h>
#if defined(_WIN32)
# define EXPORT __declspec(dllexport)
#else
# define EXPORT
#endif
EXPORT PyObject *tp = NULL;
EXPORT int i = 123;
EXPORT char *s = "Gainarie";
EXPORT float f = -3.14;
EXPORT void initTpl() {
tp = PyTuple_New(2);
PyTuple_SET_ITEM(tp, 0, PyLong_FromLong(7));
PyTuple_SET_ITEM(tp, 1, PyLong_FromLong(-9));
}
код.py :
#!/usr/bin/env python3
import sys
import ctypes
def main():
dll = ctypes.PyDLL("./dll.so")
i = ctypes.c_int.in_dll(dll, "i")
s = ctypes.c_char_p.in_dll(dll, "s")
f = ctypes.c_float.in_dll(dll, "f")
dll.initTpl()
tp = ctypes.py_object.in_dll(dll, "tp")
print(i.value, s.value, f.value, tp.value, type(tp.value))
if __name__ == "__main__":
print("Python {:s} on {:s}\n".format(sys.version, sys.platform))
main()
Примечания :
- Я тестировал только на Win , так как я не передавал свои файлы на Lnx VM , но это не должно быть проблемой
- Так как это только для демонстрационных целей, меня не заботили утечки памяти (и при этом я не проверял, * Py_XDECREF необходимо)
Выход :
e:\Work\Dev\StackOverflow\q054429301>dir /b
code.py
dll.c
e:\Work\Dev\StackOverflow\q054429301>"c:\Install\x86\Microsoft\Visual Studio Community\2015\vc\vcvarsall.bat" x64
e:\Work\Dev\StackOverflow\q054429301>cl /nologo /DDLL /MD /I"c:\Install\x64\Python\Python\03.06.08\include" dll.c /link /NOLOGO /DLL /LIBPATH:"c:\Install\x64\Python\Python\03.06.08\libs" /OUT:dll.so
dll.c
Creating library dll.lib and object dll.exp
e:\Work\Dev\StackOverflow\q054429301>dir /b
code.py
dll.c
dll.exp
dll.lib
dll.obj
dll.so
e:\Work\Dev\StackOverflow\q054429301>"e:\Work\Dev\VEnvs\py_064_03.06.08_test0\Scripts\python.exe" code.py
Python 3.6.8 (tags/v3.6.8:3c6b436a57, Dec 24 2018, 00:16:47) [MSC v.1916 64 bit (AMD64)] on win32
123 b'Gainarie' -3.140000104904175 (7, -9) <class 'tuple'>