Car*_*ers 58 c c++ vb6 dll gcc
我想制作一个简单,简单的DLL,它导出一个或两个函数,然后尝试从另一个程序中调用它...到目前为止,我看到的每个地方,都是复杂的事情,将事物连接在一起的不同方式,奇怪的问题,我还没有开始意识到存在......我只是想通过做这样的事情来开始:
创建一个导出一些函数的DLL,比如
int add2(int num){
return num + 2;
}
int mult(int num1, int num2){
int product;
product = num1 * num2;
return product;
}
Run Code Online (Sandbox Code Playgroud)
我正在使用MinGW进行编译,我想在C中做到这一点,但如果在C++中做任何真正的差异,我也想知道它们.我想知道如何将该DLL加载到另一个C(和C++)程序,然后从中调用这些函数.在玩了一些DLL之后,我的目标是通过将DLL加载到visual basic中来制作用于C(++)代码的VB前端(我有视觉工作室6,我只想制作一些表格和这些表单上的对象的事件,调用DLL).
我需要知道如何调用gcc(/ g ++)来创建一个DLL,还需要知道如何编写(/生成)导出文件...以及我能在DLL中做什么/不能做什么(比如,我可以采取来自VB前端的指针/引用的参数?DLL可以在前端调用理论函数吗?或者有一个函数从VB调用"函数指针"(我甚至不知道是否可能)它?)我很确定我不能将变量传递给DLL ......但这就是我所知道的.
好吧,我想出了如何使用gcc编译它,以使我运行的dll
gcc -c -DBUILD_DLL dll.c
gcc -shared -o mydll.dll dll.o -Wl,--out-implib,libmessage.a
Run Code Online (Sandbox Code Playgroud)
然后我有另一个程序加载它并测试函数,它工作得很好,非常感谢建议,但我尝试用VB6加载它,就像这样
Public Declare Function add2 Lib "C:\c\dll\mydll.dll" (num As Integer) As Integer
Run Code Online (Sandbox Code Playgroud)
然后我只是从表单调用add2(text1.text),但它给了我一个运行时错误:
"在C:\ c\dll\mydll.dll中找不到DLL入口点add2"
这是我为DLL编译的代码:
#ifdef BUILD_DLL
#define EXPORT __declspec(dllexport)
#else
#define EXPORT __declspec(dllimport)
#endif
EXPORT int __stdcall add2(int num){
return num + 2;
}
EXPORT int __stdcall mul(int num1, int num2){
return num1 * num2;
}
Run Code Online (Sandbox Code Playgroud)
尽管如此,从C程序中调用它是有效的:
#include<stdio.h>
#include<windows.h>
int main(){
HANDLE ldll;
int (*add2)(int);
int (*mul)(int,int);
ldll = LoadLibrary("mydll.dll");
if(ldll>(void*)HINSTANCE_ERROR){
add2 = GetProcAddress(ldll, "add2");
mul = GetProcAddress(ldll, "mul");
printf("add2(3): %d\nmul(4,5): %d", add2(3), mul(4,5));
} else {
printf("ERROR.");
}
}
Run Code Online (Sandbox Code Playgroud)
有任何想法吗?
为了解决上一个问题,我只需要像这样编译它:
gcc -c -DBUILD_DLL dll.c
gcc -shared -o mydll.dll dll.o -Wl,--add-stdcall-alias
Run Code Online (Sandbox Code Playgroud)
并在VB6中使用此API调用
Public Declare Function add2 Lib "C:\c\dll\mydll" _
(ByVal num As Integer) As Integer
Run Code Online (Sandbox Code Playgroud)
我学会了不要忘记明确指定ByVal或ByRef - 我只是回到我传递的参数的地址,它看起来像-3048.
小智 25
关于使用MinGW构建DLL,这里有一些非常简短的说明.
首先,您需要标记要导出的函数,以便DLL的调用者可以使用它们.要做到这一点,修改它们看起来像(例如)
__declspec( dllexport ) int add2(int num){
return num + 2;
}
Run Code Online (Sandbox Code Playgroud)
然后,假设您的函数位于名为funcs.c的文件中,您可以编译它们:
gcc -shared -o mylib.dll funcs.c
Run Code Online (Sandbox Code Playgroud)
-shared标志告诉gcc创建一个DLL.
要检查DLL是否实际导出了函数,请获取免费的Dependency Walker工具并使用它来检查DLL.
对于一个免费的IDE,它将自动化构建DLL所需的所有标志等,看看优秀的Code :: Blocks,它与MinGW非常兼容.
编辑:有关此主题的更多详细信息,请参阅MinGW Wiki上的创建用于Visual Basic的MinGW DLL的文章.
这是你如何做到的:
在.h
#ifdef BUILD_DLL
#define EXPORT __declspec(dllexport)
#else
#define EXPORT __declspec(dllimport)
#endif
extern "C" // Only if you are using C++ rather than C
{
EXPORT int __stdcall add2(int num);
EXPORT int __stdcall mult(int num1, int num2);
}
Run Code Online (Sandbox Code Playgroud)
在.cpp
extern "C" // Only if you are using C++ rather than C
{
EXPORT int __stdcall add2(int num)
{
return num + 2;
}
EXPORT int __stdcall mult(int num1, int num2)
{
int product;
product = num1 * num2;
return product;
}
}
Run Code Online (Sandbox Code Playgroud)
宏告诉你的模块(即你的.cpp文件)他们正在向外界提供dll内容.包含.h文件的人想要导入相同的函数,因此他们将EXPORT卖给告诉链接器导入.您需要将BUILD_DLL添加到项目编译选项中,并且您可能希望将其重命名为明显特定于项目的内容(如果dll使用您的dll).
您可能还需要创建.def文件来重命名函数并对名称进行反模糊处理(C/C++修改这些名称).这篇博文可能是一个有趣的启动点.
加载自己的自定义dll就像加载系统dll一样.只需确保DLL在您的系统路径上.C:\ windows \或你的应用程序的工作目录是一个放置你的DLL的简单的地方.
只有一个区别.你必须小心或命名mangring赢得C++.但是在Windows上你需要注意1)解析从DLL导出的函数2)编写一个所谓的.def文件,列出所有导出的符号.
在Windows中编译DLL时必须使用
__declspec(dllexport)的
但在使用它时你必须写__declspec(dllimport)
所以通常的做法是这样的
#ifdef BUILD_DLL
#define EXPORT __declspec(dllexport)
#else
#define EXPORT __declspec(dllimport)
#endif
Run Code Online (Sandbox Code Playgroud)
命名有点令人困惑,因为它通常被命名为EXPORT ..但这就是你在大多数头文件中找到的东西.所以在你的情况下你会写(使用上面的#define)
int DLL_EXPORT add .... int DLL_EXPORT mult ...
请记住,您必须在构建共享库期间添加预处理器指令BUILD_DLL.
关心弗里德里希