CB 调用 VC 的DLL 出错接口头文件#include stringtypedef unsigned int uintstruct IMpkManip{virtual
CB 调用 VC 的DLL 出错
接口头文件
#include <string>
typedef unsigned int uint;
struct IMpkManip
{
virtual void release() = 0;
virtual bool addFile(const char* sourceFilename,const char* targetFilename,bool replaceExist = true,bool compress = true,bool encrypt =false) = 0;
};
extern "C" __declspec(dllexport) IMpkManip* createMpkManip();
然后我在 VC 里面调用这个DLL 正常
#include "IMpkManip.h"
#include <windows.h>
#include <stdlib.h>
using namespace std;
int main()
{
HMODULE pDll = LoadLibrary("Base.dll");
typedef IMpkManip* (*CREATEMPKMANIP)();
CREATEMPKMANIP pShowDlg = (CREATEMPKMANIP)GetProcAddress(pDll,"createMpkManip");
IMpkManip* wwManip = pShowDlg();
wwManip->addFile("c:\\1.txt","1.txt",true,true,false);
system("pause");
return 0;
}
在 C++Builder 里面调用就不正常.
#include <windows.h>
#include <iostream>
#include <stdlib.h>
#include "IMpkManip.h"
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
HMODULE pDll = LoadLibrary("Base.dll");
typedef IMpkManip* (*CREATEMPKMANIP)();
CREATEMPKMANIP pShowDlg = (CREATEMPKMANIP)GetProcAddress(pDll,"createMpkManip");
IMpkManip* wwManip = pShowDlg();
wwManip->addFile("c:\\1.txt","1.txt",true,true,false);
system("pause");
return 0;
}
为什么啊??
[解决办法]两个问题:
1. 在 dll 和 exe 中都应该指定调入方式,如 WINAPI (也就是__stdcall)
extern "C" __declspec(dllexport) IMpkManip* __stdcall createMpkManip();
2. 一般不要跨开发工具导出类指针,而是导出标准函数,如 int, unsigned char 等
[解决办法]调用约定:
__cdecl 缺省
是 Borland C++ 的缺省的 C 格式命名约定,它在标识符前加一下划线,以保留
它原来所有的全程标识符。参数按最右边参数优先的原则传递给栈,然后清栈。
extaern "C" bool __cdecl TestFunction();
在 def 文件中显示为
TestFunction@1
注释: @1 表示函数的顺序数,将在“使用别名”时使用。
__pascal Pascal格式
这时函数名全部变成大写,第一个参数先压栈,然后清栈。
TESTFUNCTION@1//def file
__stdcall 标准调用
最后一个参数先压栈,然后清栈。
TestFunction@1//def file
__fastcall 把参数传递给寄存器
第一个参数先压栈,然后清栈。
@TestFunction@1//def file
[解决办法]CB有时就出这样的问题,不行就再用一个DLL封装一下
[解决办法]我也碰到过几次这样的事情,都是自己用VC再做个DLL重新封装,也不是很麻烦,如果原DLL的输出函数很多很复杂的话,可以把一部分业务逻辑也封装进去,简化调用接口;如果简单的话,就直接封装成个warpper就行了
[解决办法]这个好像是控制不了的,可能与COFF转OMF的过程有关,所以现在我已经打算放弃CB了,还是用VC省心
[解决办法]参考下我这里的,
http://blog.csdn.net/zhouzhangkui/article/details/5815797
你的问题 可能主要出在 _declspec(dllexport) 、__stdcall 等约定上
仔细检查下
[解决办法]俺也好奇,它返回前调用了 [[eax]+$28],跟踪看看这个eax是啥对象,到底干了啥
[解决办法]首先确定调用约定,VC demo里是this call,this指针通过ecx传递,其他参数通过堆栈由右向左传递,函数返回时,由被调用函数负责恢复堆栈;CB demo里是__cdecl,所有参数通过堆栈由右向左传递,函数返回时,由调用函数负责恢复堆栈。
这就能解释为什么你看到VC里push 5次,CB里push 6次(最后一次push eax是传递IMpkManip this指针)。
[解决办法]总之,不要这么玩。
[解决办法]不管VC还是CB,他们都是第二个参数,第一个是this。
[解决办法]跨编译器dll,不要使用类、虚函数。如果你非要这么做,可以做成com。
不同编译器,类成员的内存布局是不同的,虚函数table实现也不一样。
一般,dll尽可能只使用基本类型作为参数。
[解决办法]补充,不同编译器类成员内存布局可能是不同的。