用C/C++编译DLL,然后从另一个程序中调用它

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的文章.


Tom*_*eys 7

这是你如何做到的:

在.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的简单的地方.


Fri*_*ich 6

只有一个区别.你必须小心或命名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.

关心弗里德里希