【问题标题】:How to use the cl command?如何使用 cl 命令?
【发布时间】:2010-09-09 18:51:33
【问题描述】:

所有,我找到了一条关于如何在python中调用c文件的资料,在这些例子中:有一个c文件,其中包含许多其他头文件,这个c文件的最开始是#include Python.h,然后我发现#include Python.h其实涉及到很多很多其他的头文件,比如pystate.hobject.h等等,所以我把需要的头文件都包含进去了。在 cpp IDE 环境中,它没有显示错误。 我要做的是在python中调用这个c代码,所以from ctypes import *,那么看来dll应该是由cl -LD test.c -test.dll之类的代码生成的,但是怎么用cl 在这种情况下?我使用了 cygwin:gcc,它运行良好。谁能帮我解决这个即:在python中调用C?我说清楚了吗?提前谢谢你!

好吧,现在我觉得告诉我我做了什么很重要: 我想达到的最终目标是: 我很懒,不想用python重写那些c代码,(在某些情况下这对我来说很复杂),所以我只想生成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、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)  

谁能试试这个并告诉我你得到了什么?谢谢!

【问题讨论】:

  • 这真的和Python无关,你只是问如何在命令行上运行微软工具链的编译器。请考虑相应地标记您的问题。
  • @Jim:也许我应该补充一点:如何从 c 生成一个 dll 文件以便 python 可以调用它,就像在 windows 中一样,IDE 会发出烦人的噪音,这与代码本身无关跨度>
  • 看,也许您真正的问题与您遇到的“噪音”有关,但是您已经自己提出了解决方案,即从命令行编译。相反,您可以询问如何配置您的 IDE 以消除这种噪音,或者,如果噪音以任何方式有意义。

标签: python c compiler-construction


【解决方案1】:

你会发现微软C++编译器here的命令行选项。

考虑以下 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" 来去掉name mangling。然后我继续从命令行编译代码,如下所示:

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。

【讨论】:

  • 您能否编辑您的问题以提示当前状态或您的问题,即包括您迄今为止尝试过的内容、收到的错误消息以及您认为它不起作用的原因/原因。
  • 好的,对不起,我出去办事了,所以没看到你的帖子,我现在就发,非常感谢你
猜你喜欢
  • 2017-06-15
  • 1970-01-01
  • 2020-11-24
  • 1970-01-01
  • 2023-03-11
  • 1970-01-01
  • 1970-01-01
  • 2016-12-11
  • 1970-01-01
相关资源
最近更新 更多