Как использовать команду cl? - PullRequest
1 голос
/ 09 сентября 2010

Все, я нашел информацию о том, как вызывать c-файлы в python, в этих примерах: есть ac-файл, который включает в себя много других заголовочных файлов, самое начало этих c-файлов - #include Python.h, затем я обнаружил, что #include Python.h на самом деле включает в себя много других заголовочных файлов, таких как pystate.h, object.h и т. д., поэтому я включаю все необходимые заголовочные файлы. В среде IDE cpp он не показывал ошибок. То, что я пытаюсь сделать, это назвать этот код c в python , поэтому from ctypes import *, тогда кажется, что dll должен быть сгенерирован таким кодом, как: cl -LD test.c -test.dll, но как использовать cl в этом случае? Я использовал cygwin: gcc, он работал нормально. Может ли кто-нибудь помочь мне с этим , т.е. позвонить в C на Python ? Я проясняю себя? Заранее спасибо !!

Ну, теперь я чувствую, что важно рассказать мне, что я сделал: Конечная цель, которую я хочу достичь: Я ленивый, я не хочу переписывать эти c-коды на python (что очень сложно для меня в некоторых случаях), поэтому я просто хочу сгенерировать dll файлы, которые Python может вызвать. Я последовал примеру, приведенному в googleing «вызов python 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, скомпилировать под windows:

cl -LD test.c -test.dll

Я использовал cl в командной строке Windows, он не будет работать!

Это коды Python:

from ctypes import *   
import os  
libtest = cdll.LoadLibrary(os.getcwd() + '/test.so')  
print test.multiply(2, 2)  

Может кто-нибудь попробовать это и сказать мне, что вы получаете? спасибо!

1 Ответ

2 голосов
/ 09 сентября 2010

Здесь вы найдете параметры командной строки компилятора Microsoft C ++ здесь .

Рассмотрите следующие ключи для cl:

/nologo /GS /fp:precise /Zc:forScope /Gd

... и свяжите свойфайл с использованием

/NOLOGO /OUT:"your.dll" /DLL <your lib files> /SUBSYSTEM:WINDOWS /MACHINE:X86 /DYNAMICBASE

Пожалуйста, посмотрите, что эти опции значат в деталях, я только перечислил общие.Тем не менее, вы должны знать об их эффекте, поэтому постарайтесь избегать копирования и вставки и убедитесь, что это действительно то, что вам нужно - приведенная выше документация поможет вам.Это просто настройка, которую я использую более или менее часто.

Имейте в виду, что вы всегда можете открыть Visual Studio, настроить параметры сборки и скопировать вызовы командной строки из диалогового окна конфигурации проекта.

Редактировать: Хорошо, вот еще один совет, учитывая новую информацию, которую вы отредактировали в свой первоначальный вопрос.Я взял пример кода вашей простой 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", чтобы избавиться от искажения имени .Затем я приступил к компиляции кода из командной строки следующим образом:

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, напримерthis:

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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...