2

所以我正在学习使用 Python ctypes 模块。
这是我在 Windows 上使用 gcc -shared(4.8 版)编译的简单 C 文件,以获取示例 .dll:

#include <stdio.h>
int addition(int a, int b){
    return a+b;
}

我现在可以像这样从 Python 访问它:

>>>from ctypes import *
>>>mylibc = CDLL(r"somepath\mysample.dll")
>>>mylibc.addition
<_FuncPtr object at 0x00000000031456C8>
>>>mylibc.addition(2,3)
5

现在我尝试对包含此函数的不同、更大和更复杂的 .c 文件做同样的事情:

__declspec(dllexport) void __stdcall
flopequity(HW hero[], HW villain[], double hcounters[],
double vcounters[], double hsums[], double vsums[], ulong board,
__int32 lenh, __int32 lenv)

其中 HW 是结构的 typedef。我用 GCC 编译它并且可以像以前一样访问该函数但是当我删除 __declspec(dllexport) 或 _ stdcall (或两者)时,该函数不再可访问。
我的问题是我能够从第一个示例中访问简单功能但我无法访问更复杂功能的原因可能是什么。
编译 C 代码并从 ctypes 访问它时使用调用约定/ _declspec 的规则是什么?

4

1 回答 1

4

gcc似乎默认导出函数,您可以使用任何 PE 查看器,如 PE Explorer (View > Export) 来查看导出的函数:

在此处输入图像描述

但是,如果你尝试用 VC++ 编译这段代码,它不会为你导出这个函数,你会看到没有导出函数:

在此处输入图像描述

您需要要求它导出此功能:

__declspec(dllexport) int addition(int a, int b){
    return a+b;
}

至于调用约定,规则很简单:

如果您的函数使用__stdcall,就像大多数 Win32API 一样,您需要使用WinDLL('mylib.dll')or导入 DLL windll.mylib,例如:

> type mylib.c
__declspec(dllexport) int __stdcall addition(int a, int b) {
    return a+b;
}

***********************************************************************

> cl mylib.c /link /dll /out:mylib.dll
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.762 for 80x86

Copyright (C) Microsoft Corporation.  All rights reserved.

mylib.c
Microsoft (R) Incremental Linker Version 8.00.50727.762
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:mylib.exe
/dll
/out:mylib.dll
mylib.obj
   Creating library mylib.lib and object mylib.exp

***********************************************************************

> python
>>> from ctypes import *
>>>
>>> WinDLL('mylib.dll').addition(1, 2)
3
>>> windll.mylib.addition(1, 2)
3
>>>

如果您的函数使用__cdecl,witch 是默认调用约定,您需要使用CDLL('mylib.dll')or导入 DLL cdll.mylib',例如:

> type mylib.c
// `__cdecl` is not needed, since it's the default calling convention
__declspec(dllexport) int addition(int a, int b){
    return a+b;
}

***********************************************************************

> cl mylib.c /link /dll /out:mylib.dll
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.762 for 80x86

Copyright (C) Microsoft Corporation.  All rights reserved.

mylib.c
Microsoft (R) Incremental Linker Version 8.00.50727.762
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:mylib.exe
/dll
/out:mylib.dll
mylib.obj
   Creating library mylib.lib and object mylib.exp

***********************************************************************

> python
>>> from ctypes import *
>>>
>>> CDLL('mylib.dll').addition(1, 2)
3
>>> cdll.mylib.addition(1, 2)
3
>>>
于 2013-08-17T02:53:40.957 回答