Все, я нашел часть информации о том, как вызывать c файлы на python, в этих примерах: есть файл ac, который включает в себя множество других файлов заголовков, начало этих файлов c #include Python.h
, тогда я что #include Python.h
действительно включает в себя много других файлов заголовков, таких как pystate.h
, object.h
и т.д., поэтому я включаю все необходимые файлы заголовков. В среде cpp IDE он не обнаружил ошибок. То, что я пытаюсь сделать, это вызвать этот код c в python, поэтому from ctypes import *
, тогда кажется, что dll
должен быть сгенерирован кодом, таким как: cl -LD test.c -test.dll
, но как использовать cl
в этом случае? Я использовал cygwin: gcc
, он работал нормально. Может ли кто-нибудь помочь мне с этим i.e.: вызвать C в python? Я могу прояснить ситуацию? Спасибо заранее!
Ну, теперь я чувствую, что важно сказать мне, что я сделал:
Конечной целью, которую я хочу достичь, является:
Я ленив, я не хочу переписывать эти коды c в python (что в некоторых случаях очень сложно для меня), поэтому я просто хочу сгенерировать dll
файлы, которые может вызвать python. Я последовал примеру, указанному googleing "python call c", в этом примере есть две версии: linux и windows:
Пример test.c
:
#include <windows.h>
BOOL APIENTRY
DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved) {
return TRUE;
}
__declspec(dllexport) int
multiply(int num1, int num2) {
return num1 * num2;
}
Две версии: 1, Complie под linux
gcc -c -fPIC test.c
gcc -shared test.o -o test.so
Я сделал это в cygwin на моей системе vista, он отлично работает;:)
2, Скомпилировать под окнами:
cl -LD test.c -test.dll
Я использовал приглашение командной строки cl в командной строке Windows, это не сработает!
Это коды питона:
from ctypes import *
import os
libtest = cdll.LoadLibrary(os.getcwd() + '/test.so')
print test.multiply(2, 2)
Может ли кто-нибудь попробовать это и рассказать мне, что вы получаете? спасибо!
Вы найдете параметры командной строки компилятора Microsoft С++ здесь.
Рассмотрим следующие переключатели для cl:
/nologo /GS /fp:precise /Zc:forScope /Gd
... и связать свой файл, используя
/NOLOGO /OUT:"your.dll" /DLL <your lib files> /SUBSYSTEM:WINDOWS /MACHINE:X86 /DYNAMICBASE
Пожалуйста, взгляните на то, что эти параметры означают в деталях, я просто перечислил общие. Тем не менее, вы должны знать об их эффекте, поэтому старайтесь избегать копирования и вставки и убедитесь, что это действительно то, что вам нужно - приведенная выше документация поможет вам. Это просто настройка, которую я использую более или менее часто.
Обратите внимание, что вы всегда можете открыть Visual Studio, настроить параметры сборки и скопировать вызовы командной строки из диалогового окна конфигурации проекта.
Edit: Хорошо, вот еще несколько советов, учитывая новую информацию, которую вы редактировали в свой исходный вопрос. Я взял пример кода вашей простой DLL и вставил его в исходный файл и сделал два изменения:
#include <windows.h>
BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
{
return TRUE;
}
extern "C" __declspec(dllexport) int __stdcall multiply(int num1, int num2)
{
return num1 * num2;
}
Прежде всего, я обычно ожидаю, что функции, экспортированные из DLL, будут использовать соглашение о вызове stdcall, просто потому, что это обычная вещь в Windows, и есть языки, которые по сути не могут справиться с cdecl, видя, что они знают только stdcall. Так что одно изменение я сделал.
Во-вторых, чтобы сделать экспорт более дружественным, я указал extern "C", чтобы избавиться от name mangling. Затем я приступил к компиляции кода из командной строки следующим образом:
cl /nologo /GS /Zc:forScope /Gd c.cpp /link /OUT:"foobar.dll" /DL kernel32.lib /SUBSYSTEM:WINDOWS /MACHINE:X86
Если вы используете инструмент DUMPBIN из набора инструментов Visual Studio, вы можете проверить свою DLL для экспорта:
dumpbin /EXPORTS foobar.dll
Видя что-то вроде этого...
ordinal hint RVA name
1 0 00001010 ?multiply@@YGHHH@Z
... вы можете заметить, что экспортированное имя получило повреждение. Обычно вам нужны четкие имена для экспорта, поэтому либо используйте файл DEF, чтобы указать экспорт более подробно, либо ярлык сверху.
Впоследствии я получаю DLL, которую я могу загрузить в Python следующим образом:
In [1]: import ctypes
In [2]: dll = ctypes.windll.LoadLibrary("foobar.dll")
In [3]: dll.multiply
Out[3]: <_FuncPtr object at 0x0928BEF3>
In [4]: dll.multiply(5, 5)
Out[4]: 25
Обратите внимание, что здесь я использую ctypes.windll, что подразумевает stdcall.