如何使用cl命令?

1 投票
1 回答
4585 浏览
提问于 2025-04-16 03:55

大家好,我找到了一些关于如何在Python中调用C文件的信息。在这些例子中,有一个C文件,它包含了很多其他的头文件,这个C文件的开头是#include Python.h。然后我发现#include Python.h实际上还会引入很多其他的头文件,比如pystate.hobject.h等等,所以我把所有需要的头文件都包含进来了。在一个C++的开发环境中,它没有显示错误。我想做的是在Python中调用这个C代码,所以我用了from ctypes import *,然后似乎需要通过像cl -LD test.c -test.dll这样的代码生成一个dll文件,但在这种情况下我该如何使用cl呢?我用了Cygwin中的gcc,它运行得很好。有没有人能帮我解决这个也就是说:在Python中调用C代码的问题?我说清楚了吗?谢谢大家!

好吧,现在我觉得有必要告诉大家我做了什么:我想达到的最终目标是:我很懒,不想把那些C代码重新写成Python代码(在某些情况下对我来说非常复杂),所以我只想生成Python可以调用的dll文件。我按照谷歌上搜索“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. 在Linux下编译

gcc -c -fPIC test.c  
gcc -shared test.o -o test.so 

我在我的Vista系统的Cygwin中做了这个,运行得很好; :)

2. 在Windows下编译:

cl -LD test.c -test.dll

我在Windows命令行提示符中使用了cl,但它不工作!

这些是Python代码:

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

有没有人能试试这个,告诉我你得到了什么?谢谢!

1 个回答

2

你可以在这里找到微软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

如果你使用Visual Studio工具集中的DUMPBIN工具,你可以检查你的DLL导出:

dumpbin /EXPORTS foobar.dll

看到这样的输出...

ordinal hint RVA      name
    1    0 00001010 ?multiply@@YGHHH@Z

...你会注意到导出的名称被修饰了。通常你会希望导出有清晰的名称,所以要么使用DEF文件更详细地指定导出,要么使用上面的快捷方式。

最后,我得到了一个可以像这样加载到Python中的DLL:

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。

撰写回答