这两天用CB(Code::Blocks)写个小程序,要编译出DLL供VB(6)使用。CB使用mingw-gcc作为编译器,在库文件的产出上跟VC、VS之类的IDE略有不同。

由于C语言的基础知识不是太好,尤其对编译环节更是知之甚少。结果,试了几次,导出的DLL中的函数总是无法被调用。

用VB加载时总是提示"DLL调用约定错误",百度之了解到VB只能调用适配__stdcall约定(这也是其他语言也能调用C的默认方式)的函数。

于是在源文件中的函数前加上__stdcall,导出后又提示"找不到DLL入口点foo in mydll.dll",搜索得知可能是导出函数的名字有问题。

打开DLL Export Viewer,载入mydll.dll,发现函数变成了"foo@4"。

网上的说法是使用__stdcall的副作用,可以用extern "C"来避免,于是又加上extern "C",结果依旧。

还有人说可以用DEF文件来控制导出的函数名,不过我也没查到具体该怎么加入到编译过程中。

不断google&baidu之后,发现gcc可以在链接阶段通过指定--kill-at参数来消除这种情况。于是,紧接着又了解了下gcc的使用方法,尝试几次后终于成功了。

在这不得不吐槽部分人写的技术博客,很多问题就是只言片语带过,让人看得云里雾里。我觉得人可以说错话,但是起码要把自己的意思表达清楚,不然胡乱凑出一篇误人误己。

这里编写个简单例子来说明下具体是如何操作的:

建立DLL项目,结构如下:

  1. test/
  2. ----mydll.h
  3. ----mydll.c

头文件:mydll.h

  1. #ifndef __MYDLL_H__
  2. #define __MYDLL_H__
  3.  
  4. #ifdef BUILD_DLL
  5. #define DLL_EXPORT __declspec(dllexport)
  6. #else
  7. #define DLL_EXPORT __declspec(dllimport)
  8. #endif
  9.  
  10. #ifdef __cplusplus
  11. extern "C" {
  12. #endif
  13. DLL_EXPORT int __stdcall foo(int x);
  14. #ifdef __cplusplus
  15. }
  16. #endif
  17.  
  18. #endif // __MYDLL_H__

C文件:mydll.c

  1. #include "mydll.h"
  2.  
  3. DLL_EXPORT int __stdcall foo(int x) {
  4. return x;
  5. }

如果你安装了Code::Blocks(和MinGW),那么创建环境变量:

  1. MINGW_HOME="C:\Program Files\CodeBlocks\MinGW"
  2. PATH=%MINGW_HOME%\bin;%PATH%

打开命令行,进入我们的项目路径中:

  1. d:\test>
  2. #执行编译命令
  3. d:\test>mingw32-gcc -c -DBUILD_DLL mydll.c
  4. #执行链接命令,生成mydll.dll和静态库文件libmydll.a
  5. d:\test>mingw32-gcc -shared -o mydll.dll mydll.o -Wl,--kill-at,--out-implib,libmydll.a
  6. Creating library file: libmydll.a

以上,就是我们生成DLL的全过程了。

接下来,打开VB我们来验证下:

  1. Private Declare Function foo Lib "d:\test\mydll.dll" (ByVal x As Integer) As Integer
  2.  
  3. Private Sub Form_Load()
  4. Debug.Print foo()
  5. End Sub

运行OK,立即窗口输出10。

用Python测试下:

  1. >>> import ctypes
  2. >>> mydll = ctypes.windll.LoadLibrary("d:\\test\\mydll.dll")
  3. >>> print mydll.foo(10)
  4. 10
  5. >>>

好,也没问题,那么证明结果上是正确的。

当然,由于本人水平较低,文章中肯定有描述不正确的地方,各位大神如果如果看到还请不吝指教。

参考文档:

http://baike.baidu.com/view/2814224.htm

http://baike.baidu.com/view/1276580.htm?fr=aladdin

http://blog.sina.com.cn/s/blog_4b02b8d001000avi.html

MinGW(GCC)编译DLL文件的更多相关文章

  1. windows MinGW gcc 编译乱码问题

    问题描述 一般很多编辑器默认都是保存成utf-8文件,然而在输出中文的时候出现了乱码?另外试了其他方法,有的乱码,有的不乱? MinGW gcc 编译 utf-8 文件的时候乱码 MinGW gcc ...

  2. windows下用GCC编译DLL

    此程序有3个文件,分别为 export.h .export.c .main.c export.h 文件内容 /*此头很有必要,别人在调用的时候知道有哪些方法*/ #ifdef BUILD_DLL #d ...

  3. 在Linux下使用gcc编译mesa文件报undefined reference to symbol 'sin@@GLIBC_2.2.5和DSO missing from command line两个错误的解决方案

    一.概述 在Linux系统下使用gcc编译用C语言写的mesa的示例程序. 环境:Ubuntu Server 18.04.1 二.问题的出现 在Ubuntu下安装好mesa所需的库文件,将目标文件从g ...

  4. Ubuntu下使用gcc编译c文件,未识别cos,sin

    Ubuntu下使用gcc编译c文件,虽然我调用了math.h的头文件,但是未识别cos,sin 报错:( fft.c ) /tmp/ccwXjD8C.o: In function `fft': fft ...

  5. 反编译DLL文件

    我们平时在工作中经常会遇到一些已经被编译后的DLL,而且更加麻烦是没有源代码可以进行修改,只能针对这个DLL的文件进行修改才能得到我们想要的结果:本文将通过一个实例来演示如果完成一个简单的修改;我们将 ...

  6. 用Reflector for .NET反编译dll文件(.net),把整个dll导出个cs插件

    Reflector for .NET 下载地址: http://www.aisto.com/roeder/dotnet/ Reflector.FileDisassembler.zip下载地址: htt ...

  7. gcc 编译c++文件

    #include <stdio.h> //将类定义在命名空间中 namespace Diy{ class Student{ public: char *name; int age; flo ...

  8. 如何反编译DLL文件

    1.利用反编译器,多种工具,本次选用Reflector 8.5. 2.界面如下:

  9. dll = MinGW gcc 生成动态链接库 dll 的一些问题汇总

    MinGW gcc 生成动态链接库 dll 的一些问题汇总 https://blog.csdn.net/liyuanbhu/article/details/42612365 网络上关于用 MinGW  ...

随机推荐

  1. iOS textfield 限制输入字数长度

    iOS textfield限制输入的最大长度 [self.textFiled addTarget:self action:@selector(textFieldDidChange:) forContr ...

  2. Aspose.Cells.dll操作execl

    附件:Aspose.Cells.dll 1.创建execl(不需要服务器或者客户端安装office) public void DCExexl(DataTable dt) {  Workbook wb ...

  3. nginx+tomcat集群负载均衡(实现session复制)

    转自:http://talangniao.iteye.com/blog/341512 架构描述 前端一台nginx服务器做负载均衡器,后端放N台tomcat组成集群处理服务,通过nginx转发到后面( ...

  4. struts2.1.6教程三、在Action获取Scope对象

    引言:在前面的Action操作中,关键就是Action中的exectue方法,但是此方法并没有request.session.application等对象作为参数,自然就不能利用这些对象来操作.下面我 ...

  5. 用css3过滤做遮罩效果

    <!DOCTYPE html><html ng-app="myApp" ng-controller="myController">< ...

  6. Java ClassLoader 原理分析

    一.ClassLoader(类加载器)的作用 如果一个程序包含不止一个class文件,那么当程序启动时,带有main方法的类的class文件作为程序入口先被JVM加载,然后根据程序调用的需要,再逐步进 ...

  7. SpringMVC——数据校验

    数据校验在web应用里是非常重要的功能,尤其是在表单输入中.在这里采用Hibernate-Validator进行校验,该方法实现了JSR-303验证框架支持注解风格的验证. 一.导入jar包 若要实现 ...

  8. jquery attr处理checkbox / select 等表单元素时的坑

    先上html结构 <body> <form action=""> <input type="checkbox" id=" ...

  9. Java File类应用:递归遍历文件夹和递归删除文件

    要求: 1)采用递归遍历文件夹下的所有文件,包括子文件夹下的文件 2)采用递归删除文件下的所有文件 注意: 以下递归删除文件的方法,只能删除文件,所有的文件夹都还会存在 若要删除正文文件夹,可以在递归 ...

  10. Java IO流之打印流与标准流

    一.打印流 1.1打印流特点与构造方法 1)PrintStream和PrintWriter类都提供了一系列重载的print和println方法来输出各种类型的数据. 2)PrintStream和Pri ...