为什么需要__declspec(dllexport)来使某些功能可以从ctypes访问? [英] Why do I need __declspec(dllexport) to make some functions accessible from ctypes?

查看:255
本文介绍了为什么需要__declspec(dllexport)来使某些功能可以从ctypes访问?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我正在学习使用Python ctypes模块。

这是在Windows上使用gcc -shared(版本4.8)编译的简单C文件,以获取示例.dll:

So I am learning to make use of Python ctypes module.
Here is simple C file which I compiled with gcc -shared (version 4.8) on Windows to get sample .dll:

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

我现在可以从Python访问它,如下所示:

I am now able to access it from Python like this:

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

现在我尝试使用包含此功能的不同,更大,更复杂的.c文件来执行此操作:

Now I try to do same with different, bigger and more complicated .c file which contains this function:

__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的规则是什么?

where HW is typedef for a struct. I compile it with GCC and can access that function as before however when I remove __declspec(dllexport) or _stdcall (or both) the function is no longer accessible.
My question is what could be the reason for me being able to access the simple function from first example but me being unable to access a more complicated function. What are the rules for using calling conventions/
_declspec when compiling C code and accessing it from ctypes ?

推荐答案

gcc 似乎默认导出功能,可以使用PE浏览器(视图>导出)中的任何PE查看器来查看导出的功能:

gcc seems to export functions by default, you can use any PE viewer like PE Explorer (View > Export) to view the exported functions:

但是,如果您尝试使用VC ++编译此代码,则不会为您导出此功能,您将看到没有导出的功能:

But, If you try to compile this code with VC++, it won't export this function for you, you'll see that there is not exported function:

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

You need to ask it to export this function:

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

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

As for calling conventions, the rule is simple:

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

If your function uses __stdcall, as most Win32API, you need to import the DLL with WinDLL('mylib.dll') or windll.mylib, example:

> 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 ,则女巫默认调用约定,您需要使用 CDLL('mylib.dll') cdll.mylib',例如:

If your function uses __cdecl, witch is the default calling convention, you need to import the DLL with CDLL('mylib.dll') or cdll.mylib', example:

> 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
>>>

这篇关于为什么需要__declspec(dllexport)来使某些功能可以从ctypes访问?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆