[心缘地方]同学录
首页 | 功能说明 | 站长通知 | 最近更新 | 编码查看转换 | 代码下载 | 常见问题及讨论 | 《深入解析ASP核心技术》 | 王小鸭自动发工资条VBA版
登录系统:用户名: 密码: 如果要讨论问题,请先注册。

[整理]使用VC以_stdcall方式对DLL进行二次封装,以使VB可以调用该DLL

上一篇:[备忘]SQL Server 2005 中创建新的维护计划时出现错误消息:“创建维护计划失败”
下一篇:[备忘]Java读取CSV文件,OpenCSV,开源代码。

添加日期:2011/9/16 15:05:34 快速返回   返回列表 阅读15044次

金橙子镭雕软件提供了:
MarkEzd.dll、MarkEzdDll.h
--------------------------------
MarkEzd.dll中是使用的默认的_cdecl Calling convention,
VB中无法直接调用方法,VB总是使用_stdcall方式,二者不兼容。
VB直接调用,会报“bad dll calling convention”的错误。

所以,写了个dll,对MarkEzd.dll进行了一下封装,同时方法都声明为_stdcall方式,
这样VB就可以调用此dll,从而间接调用MarkEzd.dll中的方法了。
--------------------------------
(1)新建一个win32 dynamic-link libray的工程,把MarkEzdDll.h复制进来

(2)添加MarkEzdStdCall.cpp,内容如下:


#include "stdafx.h"
#include "tchar.h"
#include "MarkEzdDll.h"

HINSTANCE hEzdDLL;
LMC1_INITIAL lmc1_Initial;
LMC1_LOADEZDFILE lmc1_LoadEzdFile;
LMC1_CHANGETEXTBYNAME lmc1_ChangeTextByName;
LMC1_MARK lmc1_Mark;
LMC1_CLOSE lmc1_Close;

BOOL APIENTRY _stdcall DllMain( HANDLE hModule, 
    DWORD  ul_reason_for_call, 
    LPVOID lpReserved
    
{
    return TRUE;
}

__declspec(dllexport) int _stdcall stdCallStart(){
    hEzdDLL = LoadLibrary(_T("MarkEzd.dll"));
    if(hEzdDLL==NULL){
        return -1;    
    }
    
    lmc1_Initial=(LMC1_INITIAL)GetProcAddress(hEzdDLL, "lmc1_Initial");
    if(lmc1_Initial==NULL){
        return -1;    
    }

    lmc1_LoadEzdFile=(LMC1_LOADEZDFILE)GetProcAddress(hEzdDLL,"lmc1_LoadEzdFile");
    if(lmc1_LoadEzdFile==NULL){
        return -1;    
    }

    lmc1_ChangeTextByName=(LMC1_CHANGETEXTBYNAME)GetProcAddress(hEzdDLL,"lmc1_ChangeTextByName");
    if(lmc1_ChangeTextByName==NULL){
        return -1;    
    }

    lmc1_Close=(LMC1_CLOSE)GetProcAddress(hEzdDLL, "lmc1_Close");
    if(lmc1_Close==NULL){
        return -1;    
    }

    lmc1_Mark=(LMC1_MARK)GetProcAddress(hEzdDLL,"lmc1_Mark");
    if(lmc1_Mark==NULL){
        return -1;    
    }
    
    return 0;
}

__declspec(dllexport) int _stdcall stdCallEnd(){
    FreeLibrary(hEzdDLL);
    hEzdDLL = NULL;
    return 0;
}

__declspec(dllexport) int _stdcall lmc1_Initial_StdCall(TCHAR* strEzCadPath,
    BOOL bTestMode,
    HWND hOwenWnd){
    return lmc1_Initial(strEzCadPath,bTestMode,hOwenWnd);
}

__declspec(dllexport) int _stdcall lmc1_LoadEzdFile_StdCall(TCHAR* strFileName){
    return lmc1_LoadEzdFile(strFileName);
}

__declspec(dllexport) int _stdcall lmc1_ChangeTextByName_StdCall(TCHAR* strTextName, TCHAR* strTextNew){
    return lmc1_ChangeTextByName(strTextName,strTextNew);
}

__declspec(dllexport) int _stdcall lmc1_Mark_StdCall(BOOL bFlyMark){
    return lmc1_Mark(bFlyMark);
}

__declspec(dllexport) int _stdcall lmc1_Close_StdCall(){
    return lmc1_Close();
}


_stdcall就是重点了,__declspec(dllexport)是为了让函数对外部可见。

(3)确认一下,
Project-->setting-->c/c++-->Category(Code Generation)-->Calling convention 使用默认的__cdecl。

(4)创建DEF文件。
文件-->新建--C++ Source File,文件名用StdCall.def就行。
然后输入内容:


LIBRARY   MarkEzdStdCall

EXPORTS
stdCallStart    @1
stdCallEnd    @2
lmc1_Initial_StdCall    @3
lmc1_LoadEzdFile_StdCall    @4
lmc1_ChangeTextByName_StdCall    @5
lmc1_Mark_StdCall    @6
lmc1_Close_StdCall    @7



会自动在
Project-> SETTINGS-> lINK   ->Category(General) -->Projcet  Options中加入了/def:".\StdCall.def"

(4)Build DLL
-----------------------------------------
使用Depends.exe可以查看dll的可见函数列表,确认函数名称正确即可。
-----------------------------------------


如何把VC项目设置为 UNICODE版

(1)安装时
Microsoft Visual C++ 6.0/Vc++ MFC and Template Libraries/MS Foundation Class Libraries/选中两个for Unicode。

(2)菜单project->Settings弹出项目设置对话框,点击C/C++属性页,在Preprocessor definitions一栏中加入UNICODE字符串,去除MCBS字符串。

(3)点击Link属性页,在Category一栏中选择Output,然后在Entry-point symbol一栏中加入wWinMainCRTStartup字符串
这步我没有做,做了会报错。

(4)项目中所有源码中的char改成TCHAR,所有用双引号包含的字符串改成_T(“ … ”)
 

评论 COMMENTS
guest334837060
2012/9/20 10:45:31
按照你说方法去做,有几个函数不能封装,能否给出详细解答。函数好像贴不上来
guest337433877
2012/9/20 10:55:56
有这篇文章的作者联系方法吗?我想得到他的帮助!
guest661643541
2014/6/21 16:15:33
有这篇文章的作者联系方法吗?作者如看到请联系QQ:1176993468
我是作者
2014/7/6 15:33:03
不知道你想问啥,我对VC也不咋懂,我也是照葫芦画瓢,瞎搞了几下。
guest795531393
2019/6/16 20:23:30
请问作者有二次封装的dll文件吗?本人QQ:625276019 需要得到你的帮助

添加评论 Add new comment.
昵称 Name:
评论内容 Comment:
验证码(不区分大小写)
Validation Code:
(not case sensitive)
看不清?点这里换一张!(Change it here!)
 
评论由管理员查看后才能显示。the comment will be showed after it is checked by admin.
CopyRight © 心缘地方 2005-2999. All Rights Reserved