相当于python ctypes的C dll
我很有能力用python编写代码,但我想开始用C语言编写一些函数。使用ctypes,我可以很容易地打开DLL并使用函数。寻找这个等价物的简单C示例似乎是不可能的。我总是发现2页的C++例子充满了锅炉板代码,并不能真正地告诉我们正在发生什么。更糟糕的是,.Net和visual studio示例导入了各种依赖项。下面是运行良好的python代码,包括DLL函数的API文档 下面是我在代码::块中使用此dll的失败尝试相当于python ctypes的C dll,python,c,dll,ctypes,Python,C,Dll,Ctypes,我很有能力用python编写代码,但我想开始用C语言编写一些函数。使用ctypes,我可以很容易地打开DLL并使用函数。寻找这个等价物的简单C示例似乎是不可能的。我总是发现2页的C++例子充满了锅炉板代码,并不能真正地告诉我们正在发生什么。更糟糕的是,.Net和visual studio示例导入了各种依赖项。下面是运行良好的python代码,包括DLL函数的API文档 下面是我在代码::块中使用此dll的失败尝试 #include <windows.h> #include <s
#include <windows.h>
#include <stdio.h>
#include "mcp2210_dll_um.h"
int main()
{ HINSTANCE hinstDLL;
hinstDLL = LoadLibrary("mcp2210_dll_um_x86.dll");
if (hinstDLL != 0){
printf("DLL loaded ok");
char *version;
int VersionFunction;
VersionFunction = GetProcAddress(hinstDLL, "Mcp2210_GetLibraryVersion");
VersionFunction(*version);
printf(version);
}
else{
return -1;
}
FreeLibrary(hinstDLL);
return 0;
}
#包括
#包括
#包括“mcp2210_dll_um.h”
int main()
{HINSTANCE hinstDLL;
hinstDLL=LoadLibrary(“mcp2210_dll_um_x86.dll”);
如果(hinstDLL!=0){
printf(“DLL加载正常”);
字符*版本;
int-VersionFunction;
VersionFunction=GetProcAddress(hinstDLL,“Mcp2210_GetLibraryVersion”);
VersionFunction(*版本);
printf(版本);
}
否则{
返回-1;
}
免费图书馆(hinstDLL);
返回0;
}
如果我省略了尝试运行函数的行,它似乎会构建和加载dll。在C中使用此DLL的最简单方法是什么?我得到的错误是:
…\dll_test_use\main.c | 13 |错误:调用的对象“VersionFunction”为
不是函数或函数指针|
编辑:***已解决****
@dgnuff是正确的
这就是我所需要做的:
#include <stdio.h>
#include "mcp2210_dll_um.h"
int main(){
int ret_code;
wchar_t version[64];
ret_code = Mcp2210_GetLibraryVersion(version);
printf("%d\n", ret_code);
return 0;
}
#包括
#包括“mcp2210_dll_um.h”
int main(){
int ret_代码;
wchar__t版本[64];
ret_代码=Mcp2210_GetLibraryVersion(版本);
printf(“%d\n”,返回代码);
返回0;
}
之后,由于我使用的是code::blocks,我需要转到链接器设置并添加.lib文件
设置/编译器/链接设置/链接库:和添加
mcp2210_dll_um_x86.lib
这里有几个问题。首先
GetProcAddress()
返回命名函数入口点的地址。将其存储在int
中不是一件有用的事情,因为您不能有意义地调用int
值
在我脑海中,我无法告诉你Mcp2210_GetLibraryVersion()
的签名,但是一个基于python的有根据的猜测说它类似于int-Mcp2210_GetLibraryVersion(wchar\u t*version)代码>。因此,您需要将Mcp2210\u GetLibraryVersion
变量声明为指向相应函数签名的指针。web上有关于此详细信息的任意数量:
综上所述,虽然LoadLibrary()
是从C代码访问DLL的一种方法,但出于许多原因,如果静态链接DLL,通常会更好。我注意到您的源代码中有这一行:
#include "mcp2210_dll_um.h"
它很可能是正在加载的DLL的“导入头”。如果是这种情况,那么您实际上不需要执行LoadLibrary()
GetProcAddress()
sheanigans,您可以直接调用所讨论的例程,链接器/可执行加载程序将为您带来所有的魔力
这取决于它们是否是一个合适的mcp2210_dll_um.lib
库文件,您可以将其链接到您的项目中:这就是“导入库”,它有助于实现这一切
另一个问题是,正如所写的那样,使用version
变量几乎肯定不会像您希望的那样工作。这是一个完全不同的问题,正如在许多问题中提到的,数组和指针之间的差异和相似性在早期的C经验中可能会引起相当多的混淆
这里的底线假设Mcp2210\u GetLibraryVersion()
确实采用宽字符指针,并用一个保存版本的字符串填充指向的位置
在这种情况下,您希望将版本声明为数组,而不是指针:
wchar_t version[64];
应该与python声明完全匹配:
version = (c_wchar * 64)()
在原始char*版本中创建数组代码>仅创建了一个指针wchar\u t
是python的C\u wchar
的C等价物
现在,要将该数组传递到Mcp2210\u GetLibraryVersion()
中,只需将其命名为:
Mcp2210_GetLibraryVersion(version);
C(和C++)可能会对数组和指针的工作方式、它们各自是什么以及它们如何相互作用产生一些混淆
真正简短的答案是数组是固定的,无论它们在哪里声明,并且由指定数量的对象组成,所有对象在内存中彼此相邻
另一方面,指针是某物的地址。因此,仅仅声明一个指向(例如,wchar\u t
的指针实际上并不会分配任何wchar\u t
,它只会给您一些可以保存您选择的任何wchar\u t
地址的内容
--编辑以澄清静态DLL的用法--
从您在评论中所说的内容来看,应该很简单,只要将头文件包含在C源文件中(您已经在这样做了),然后直接在C源文件中调用函数即可:
wchar_t version[64];
int retval = Mcp2210_GetLibraryVersion(version);
您需要小心地将version
处理为printf()
,因为version是一个宽字符串,默认情况下,printf()
处理普通的char
字符串。查看\u wprintf()
或\u tprintf()
以使其正常工作
至于库中的链接,如何实现这一点取决于您是直接从命令行或makefile调用链接器,还是作为Visual Studio项目进行构建
在前一种情况下,您将有类似
link.exe /option /option filename.obj other_filename.obj etc. etc. etc.
只需将库mcp2210_dll_um_x86.lib
添加到命令行,它就可以工作了。请注意,如果库在其他目录中处于关闭状态,则可以使用
wchar_t version[64];
int retval = Mcp2210_GetLibraryVersion(version);
link.exe /option /option filename.obj other_filename.obj etc. etc. etc.