C+的dll如何用易语言正确调用?

Python010

C+的dll如何用易语言正确调用?,第1张

在编写程序的时候往往需要调用到别的语言编写的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文件导出是一样的道理。

这是我之前写的一个 易语言做的取网页源码的 你可以参考下

void CMyDlg::OnOK()

{

// TODO: Add extra validation here

HINSTANCE hMod = LoadLibrary("MyDll.dll")

//载入Mydll.dll

typedef char *(WINAPI *ADD)(CString)

//添加一个函数 char 返回字符串 WINAPI ADD添加 CString 输入字符串

ADD App_Add = (ADD)GetProcAddress(hMod,"App_Add")

//添加函数名

CString str

//设置个字符串变量

char *sc

//char *字符串 sc

CString URL

//CString 为网址

GetDlgItemText(IDC_EDIT2,URL)

//获取IDC_EDIT2 为编辑框的ID URL 获取编辑框的内容

sc=App_Add(URL)

//App_Add 为函数 执行 获取URL网址源码, 传递参数为字符串 URL sc获取源码

str=(sc)

//sc char* 转成CString

GetDlgItem(IDC_EDIT1)->SetWindowText(str)

//把转好的str输入到编辑框1ID为 IDC_EDIT1

sc=App_Add("http://mccpx.top/XXP/time.php")

//sc=获取网络时间

str=(sc)

//转成CString

GetDlgItem(IDC_STATIC)->SetWindowText(str)

//输出 标签IDC_STATIC

FreeLibrary(hMod)

//关闭Dll句柄

//关闭 CDialog::OnOK() IDC_EDIT1

}

不懂在追问

如果易语言编译器容许您,那么就是可以的,例如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调用的问题)

  http://www.aidianying123.net/article/?29.html

以便您对此更加了解。