重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
你用
我们提供的服务有:成都网站设计、成都做网站、微信公众号开发、网站优化、网站认证、大庆ssl等。为超过千家企事业单位解决了网站和推广的问题。提供周到的售前咨询和贴心的售后服务,是有科学管理、有技术的大庆网站制作公司
__declspec
(dllexport)
来写DLL函数头的话这个DLL只能被C或C++调用
将函数写到
.DEF
文件的话可以让所有编程语言都能调用
在编写程序的时候往往需要调用到别的语言编写的DLL文件,下面先来看一下在易语言中如何调用VC编写的DLL呢,首先用VC编写一个简单的DLL文件,代码如下:
int WINAPI add(int x,int y)
{
return x+y;
}
这是一个简单的两个数加法操作,返回两个数相加的结果,这里我生成的是MFC DLL,并且需要在def中导出add函数。
下面用易语言来调用它,首先在易语言中需要插入一个DLL命令,代码如下:
.版本 2
.DLL命令 调用CDLL, 整数型, "cdll.dll", "add"
.参数 x, 整数型
.参数 y, 整数型
并且保存工程文件与DLL文件在一起,否则可能会报找不到DLL的错误.下面在按钮中添加如下代码:
.版本 2
.子程序 _按钮1_被单击
信息框 (调用CDLL (5, 5), 0, )
这样我们传递了两个数后就可以返回结果了,如下图:
上图的信息框显示返回的结果是10,那么这就是正确的了,易语言调用VC的DLL需要注意类型,并且DLL函数需要WINAPI或stdcall,否则也会报错。
下面我们再来看一下VC如何调用易语言的DLL,还是先用易语言编写一个DLL文件,建立一个DLL动态链接库工程,新建一个子程序,代码如下:
.版本 2
.子程序 add, 整数型, 公开
.参数 x, 整数型
.参数 y, 整数型
返回 (x + y)
下面我们用VC来调用这个DLL并且返回结果,代码如下:
HINSTANCE hMod = LoadLibrary("e.dll");
typedef int(WINAPI *ADD)(int,int);
ADD myadd = (ADD)GetProcAddress(hMod,"add");
CString str;
str.Format("%d",myadd(5,5));
MessageBox(str);
FreeLibrary(hMod);
调用后结果如下图:
这样就得到了正确的结果了,需要注意的是易语言子程序必须公开,公开也就是与VC中def文件导出是一样的道理。
如果易语言编译器容许您,那么就是可以的,例如keilc51编译器和常用调试arm裸机程序,是可以在c语言语句中加入汇编语言。
由于本人不了解易语言,无法确定其编译器是否可以编译c,但估计是不行。
那么说回来,如果这样,程序就没法写了。实际大家是怎么做的呢。通常做法是将c语言程序编译成dll文件,也就是我们所谓的库文件。然后就可以实现调用了。这种文件我们经常会在常见的程序中看到,原因就是代码保密性好,并且更新很方便,关键在于可以多种语言交互。
当然了,也可以吧所谓的易语言封装成dll,被c调用,当然如果他有这项功能的话。
如果一个c语言已经编译成可执行程序了,比如exe文件,那么易语言端应与c语言端进行进程通信,方可实现数据交互。那么进程通信就有多种方式,那么就不赘述了。
说下DLL的封装,如果是c语言我们需要加入dll.h
dll.h中放入以下语句
#ifndef _DLL_H_
#define _DLL_H_
#if BUILDING_DLL
# define DLLIMPORT __declspec (dllexport)
#else /* Not BUILDING_DLL */
# define DLLIMPORT __declspec (dllimport)
#endif /* Not BUILDING_DLL */
DLLIMPORT void HelloWorld (void);
#include "func.h"
#endif /* _DLL_H_ */
程序中的,DLLIMPORT void HelloWorld (void);,#include "func.h"是例子,就是放你书写的用c写的函数声明的地方。
而在你c语言原先放主函数的那个文件中应该写入以下内容
/* Replace "dll.h" with the name of your header */
#include "dll.h"
#include windows.h
#include stdio.h
#include stdlib.h
BOOL APIENTRY DllMain (HINSTANCE hInst /* Library instance handle. */ ,
DWORD reason /* Reason this function is being called. */ ,
LPVOID reserved /* Not used. */ )
{
switch (reason)
{
case DLL_PROCESS_ATTACH:
break;
case DLL_PROCESS_DETACH:
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
}
/* Returns TRUE on success, FALSE on failure */
return TRUE;
}
我们看见有很多case,也有很多传入参数,最初可以不用管它,也可以使用。如需详细配置,应自行梳理再做决定。
另外一点,对于高级语言和c语言清理现场的问题,也就是被调用函数结束后由被调用函数清理栈,还是由下一个被执行函数清理上一个函数的栈,这点很重要。两种不同的调用方式将导致你虽然可以调用dll,但可能数据出错。这个问题可以说在VB与C的交互上面就可以体现了。__cdecl这个就是默认c语言的栈处理方式。__stdcall是VB的处理方式,那么对于易语言,请您详细查看后再做定论。
那么具体在c语言中提现就是,我们需要在函数前面加上__stdcall以告知编译器采用此类编译方式,应用方法就如下面的声明。
#ifndef _FUNC_H_
#define _FUNC_H_
#include "dll.h"
#include winsock2.h
#include "var.h"
DLLIMPORT __stdcall void GetProgressNumFileIDPackageID(int *PercentNum,int *FileID,int *PackageID);
DLLIMPORT __stdcall int GetInfoNum(int Mode);
DLLIMPORT __stdcall void PutInfoNum(int InfoNum,int Mode);
DLLIMPORT __stdcall void Demo0(void);
DLLIMPORT __stdcall void Demo1(void);
DLLIMPORT __stdcall void InitThreadCriticalSection(void);
DLLIMPORT __stdcall void DeleteThreadCriticalSection(void);
#endif /*_FUNC_H_*/
我听说VB和易语言有相似之处那么我给出VB调用C语言DLL时候的函数书写例子,以便您参考。
Public Class Form1
Private Declare Sub NetToWork Lib "Client.dll" (ByVal IpAddr As String, ByVal Port As Integer, ByVal Mode As Integer)
Private Declare Function StrToStruct Lib "Client.dll" (ByVal Str As String, ByVal Mode As Integer) As Integer
Private Declare Function StructToStr Lib "Client.dll" (ByVal Str As String, ByVal Mode As Integer) As Integer
Private Declare Function GetInfoNum Lib "Client.dll" (ByVal Mode As Integer) As Integer
Private Declare Sub PutInfoNum Lib "Client.dll" (ByVal InfoNum As Integer, ByVal Mode As Integer)
Private Declare Sub Demo0 Lib "Client.dll" ()
Private Declare Sub Demo1 Lib "Client.dll" ()
.........
...
..
...
Private Sub ToolStripButton1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ToolStripButton1.Click
'从text搜索关键词 并读取回链表数据
Dim Str As String
If (ToolStripTextBox1.Text = "") Then
MsgBox("内容不能为空")
Else
Str = ToolStripTextBox1.Text
StrToStruct(Str, SEND_SEARCH_0200)
Dim Th0 As Threading.Thread
Th0 = New Threading.Thread(AddressOf DownFileList)
Th0.Start()
End If
End Sub
....
..
上程序但中StrToStruct(Str, SEND_SEARCH_0200)就是一个典型的VB调用DLL函数的例子。
那么如果给些相关的参考资料(C语言封装DLL以及VB调用的问题)
以便您对此更加了解。
C#编写后的代码是基于CLR公共语言运行库上的,是不同于C++输出的传统DLL,所以不能被易语言中调用,你所列的方法是适用于传统VC++输出的DLL,如API