0xAA55 发表于 2017-4-6 08:38:33

【VB6】使用VB6写“标准DLL”

为啥要加双引号呢?因为DLL就是DLL,没啥标准不标准的说法。这里只不过有些人认为,带COM组建的DLL就不是“标准DLL”。
方法很简单,写个假的链接器,使用它来修改链接命令,然后插入想要导出的函数就可以了。
其实这就是一个简单的编译原理的知识,或者说是“链接器原理”。献给所有喜爱编程的初学者。

VB6导出“标准DLL”(也就是不带COM类的DLL)的方法无非就是把链接器的参数改一下就好。VB6本身生成的obj和VC6的格式差不多,因为都是nasm所说的“win32”格式,所以其实VB6使用的链接器和VC6的是一样的。链接器就负责将一堆obj或者lib组合起来,生成dll或者exe。所以VB6也能生成“标准DLL”。
因为VB6默认没有“标准DLL”工程,所以大家都以为VB6不能生成“标准DLL”。但其实我们自己修改VB6的链接器参数就可以实现生成“标准”DLL。
这个的解决方案很简单。自己写一个假的链接器,用于修改命令行参数,然后把修改了的命令行参数传达给真正的链接器即可。假的链接器的写法也可以很随意。反正实现了功能就好。

我这边写了一个。它的规则是:当你的工程里面有一个叫“DLL_Module”的模块(或frm、res、cls等都会被识别)的时候,就会把当前工程认定为DLL工程,然后查找工程目录下的Dll_Module.def(模块定义文件)。如果你没有这个文件的话,它就会提示你创建这个文件(它会创建给你并自动帮你用记事本打开这个文件)。

PseudoLinker(伪链接器)下载(包含工程和源码,还有编译好的BIN):


运行BIN的时候请注意安全:
校验信息
名称: LINK.EXE
大小: 36864 字节 (36 KiB)
SHA256: 73975F6C944159B0A4A0E81EC4D0431F15CC5541134C5AD8C522FB8C722ED893

伪链接器用法:
1、进自己的VB6安装目录(我的是 C:\Program Files (x86)\Microsoft Visual Studio\VB98 )
2、找到LINK.EXE,将其改名为“ORG_LINK.EXE”
3、把我写的伪链接器LINK.EXE复制进去。搞定。


安装好这个伪链接器后,你就能写DLL工程了。写法很简单,创建一个空工程,添加一个模块,改名为DLL_Module,然后保存为DLL_Module.bas。
模块的内容有一部分内容是需要写的。这里示范了如何写一个导出函数“foo”的例子。Option Explicit

Public Const DLL_PROCESS_DETACH As Long = 0
Public Const DLL_PROCESS_ATTACH As Long = 1
Public Const DLL_THREAD_ATTACH As Long = 2
Public Const DLL_THREAD_DETACH As Long = 3

Sub Main()
' 留空
End Sub

Public Function DllMain(ByVal hInst As Long, ByVal fdwReason As Long, ByVal lpvReserved As Long) As Boolean
   Select Case fdwReason
      Case DLL_PROCESS_DETACH
         
      Case DLL_PROCESS_ATTACH
         DllMain = True
      Case DLL_THREAD_ATTACH
         
      Case DLL_THREAD_DETACH
         
   End Select
End Function

Function foo(ByVal A As Long, ByVal B As Long) As Long
foo = A + B
End Function

其中DllMain是DLL入口,Sub Main是EXE入口,保留Sub Main是为了让VB6能允许你编译它。能编译就能得到OBJ,能得到OBJ就能链接,能链接就能生成DLL。

然后,试着编译了一下,嗯因为之前我们没写DEF文件,这里果然提示了要创建DEF文件。


然后记事本弹出来了。此时修改DEF文件,添加我们要导出的函数名。


保存后,再次编译,没有意外的话应该就能成功获得DLL、EXP、LIB三个文件了。


而且它也确实导出了foo这个函数。


嗯但关键是这个DLL要别的语言也能用哈。有人跟我这样说。我只想表示,蛤?我都做出DLL了你还担心别的语言不能用?编译原理都不懂就瞎说,明明是自己无知。

来创建测试工程。废话不啰嗦,先把DLL丢输出目录,然后开始编码。
之前VB写的foo函数原型是 Function foo(ByVal A As Long, ByVal B As Long) As Long ,那么它的C语言原型应该是long _stdcall foo(long A, long B);

看。


这是编译成功的标志。事实上它运行也是成功的:


不过话说回来,我们为啥要用VB6写DLL呢?

参考阅读:
【混合编程】VB6与VC++的合体编程(不使用DLL)

Danbo.L 发表于 2017-4-6 08:58:53

这个够详细 先顶 再试试:lol

cyycoish 发表于 2017-4-6 13:30:15

不过话说回来,我们为啥要用VB6写DLL呢?
因为:“又能了解链接器原理啦,老开心的!”

Golden Blonde 发表于 2017-4-6 14:49:02

学习了!不过如果这种DLL里带界面,似乎就不能正常使用了。

0xAA55 发表于 2017-4-6 18:56:20

美俪女神 发表于 2017-4-6 14:49
学习了!不过如果这种DLL里带界面,似乎就不能正常使用了。

好像是,估计得找个机会跑一次__vbaS

0xAA66 发表于 2017-4-13 17:51:53

来支持 一下,连接器还能写C代码 汇编代码。只是VB 多变却兼容性不足罢了。。。

0xAA55 发表于 2017-4-14 14:09:40

0xAA66 发表于 2017-4-13 17:51
来支持 一下,连接器还能写C代码 汇编代码。只是VB 多变却兼容性不足罢了。。。
...

链接器并不能写代码,它只负责链接

0xAA66 发表于 2017-4-15 17:14:10

0xAA55 发表于 2017-4-14 14:09
链接器并不能写代码,它只负责链接

意思就是说,把连C的代码给连接起来。一起编译。这样就能伪C代码 写在VB中。

0xAA55 发表于 2017-4-15 19:26:50

0xAA66 发表于 2017-4-15 17:14
意思就是说,把连C的代码给连接起来。一起编译。这样就能伪C代码 写在VB中。 ...

那也不是“伪C代码”,那是组合语言编程

唐凌 发表于 2018-2-10 22:36:24

这样生成出来的lib文件应该也可以放进EXE的链接器参数里吧,然后直接在头上声明函数原型实现导入

xxdoc 发表于 2018-5-6 07:31:24

要是加上导出后自动生成导出函数声明的.那就有方便

勇芳软件 发表于 2018-6-10 19:10:20

watermelon 发表于 2018-6-11 09:00:30

tangptr@126.com 发表于 2018-2-10 22:36
这样生成出来的lib文件应该也可以放进EXE的链接器参数里吧,然后直接在头上声明函数原型实现导入 ...

应该也可以吧,这里运行时获取dll导出函数地址来调用可以,那导入lib再调用也可以应该

大宝 发表于 2020-7-8 10:07:32

本帖最后由 china_shy_wzb 于 2020-7-20 13:43 编辑

学习用VB6写DLL,受教了

imr2013 发表于 2022-11-18 16:36:16

终于知道原理了,其实只要vb工程较大,编译时在文件资源管理器就能看到obj的文件,只不过最后删除了

0xAA55 发表于 2022-11-18 21:53:58

imr2013 发表于 2022-11-18 16:36
终于知道原理了,其实只要vb工程较大,编译时在文件资源管理器就能看到obj的文件,只不过最后删除了 ...

写个假的 link.exe 就可以趁机复制 obj 备份一下。

二十六 发表于 2023-8-11 16:12:29

感谢大佬,解决了我一个很重要的难题!
页: [1]
查看完整版本: 【VB6】使用VB6写“标准DLL”