金橙子镭雕软件提供了: 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(“ … ”)
|