CB 调用 VC 的DLL 出错

爱蹄子的羊头 2013-01-31 09:03:09
接口头文件


#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;
}



为什么啊??
...全文
335 19 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
爱蹄子的羊头 2013-02-17
  • 打赏
  • 举报
回复
引用 16 楼 zcchm 的回复:
引用 1 楼 warrially 的回复:在 OllyDbg 里面下断点后发现 VC 调用的参数是正常的 C++Builder 调用的 ("c:\\1.txt") 变成了第二个参数 // 是调用约定的问题吗? 应该都是 cdecl才对啊? 不管VC还是CB,他们都是第二个参数,第一个是this。
谢谢大神. 这个 EAX 确实是 this. 但是现在有没有什么办法解决?
zcchm 2013-02-17
  • 打赏
  • 举报
回复
补充,不同编译器类成员内存布局可能是不同的。
zcchm 2013-02-17
  • 打赏
  • 举报
回复
跨编译器dll,不要使用类、虚函数。如果你非要这么做,可以做成com。 不同编译器,类成员的内存布局是不同的,虚函数table实现也不一样。 一般,dll尽可能只使用基本类型作为参数。
zcchm 2013-02-16
  • 打赏
  • 举报
回复
引用 1 楼 warrially 的回复:
在 OllyDbg 里面下断点后发现 VC 调用的参数是正常的 C++Builder 调用的 ("c:\\1.txt") 变成了第二个参数 // 是调用约定的问题吗? 应该都是 cdecl才对啊?
不管VC还是CB,他们都是第二个参数,第一个是this。
zcchm 2013-02-16
  • 打赏
  • 举报
回复
总之,不要这么玩。
zcchm 2013-02-16
  • 打赏
  • 举报
回复
引用 10 楼 dataxdata 的回复:
引用 9 楼 warrially 的回复:输出函数略多了些. 我在汇编里面看C++Builder 多压了一个参数进去. 不知道他为什么要这么做. VC 里面是 push5次 CB push5次以后 又push 了一次 eax 这个好像是控制不了的,可能与COFF转OMF的过程有关,所以现在我已经打算放弃CB了,还是用VC省心
首先确定调用约定,VC demo里是this call,this指针通过ecx传递,其他参数通过堆栈由右向左传递,函数返回时,由被调用函数负责恢复堆栈;CB demo里是__cdecl,所有参数通过堆栈由右向左传递,函数返回时,由调用函数负责恢复堆栈。 这就能解释为什么你看到VC里push 5次,CB里push 6次(最后一次push eax是传递IMpkManip this指针)。
sololie 2013-02-10
  • 打赏
  • 举报
回复
引用
输出函数略多了些. 我在汇编里面看C++Builder 多压了一个参数进去. 不知道他为什么要这么做. VC 里面是 push5次 CB push5次以后 又push 了一次 eax
俺也好奇,它返回前调用了 [[eax]+$28],跟踪看看这个eax是啥对象,到底干了啥
周药师 2013-02-05
  • 打赏
  • 举报
回复
参考下我这里的, http://blog.csdn.net/zhouzhangkui/article/details/5815797 你的问题 可能主要出在 _declspec(dllexport) 、__stdcall 等约定上 仔细检查下
爱蹄子的羊头 2013-02-01
  • 打赏
  • 举报
回复
引用 10 楼 dataxdata 的回复:
引用 9 楼 warrially 的回复:输出函数略多了些. 我在汇编里面看C++Builder 多压了一个参数进去. 不知道他为什么要这么做. VC 里面是 push5次 CB push5次以后 又push 了一次 eax 这个好像是控制不了的,可能与COFF转OMF的过程有关,所以现在我已经打算放弃CB了,还是用VC省心
要做个 工具. MFC 用起来恶心.. 想用 VCL.
dataxdata 2013-02-01
  • 打赏
  • 举报
回复
引用 9 楼 warrially 的回复:
输出函数略多了些. 我在汇编里面看C++Builder 多压了一个参数进去. 不知道他为什么要这么做. VC 里面是 push5次 CB push5次以后 又push 了一次 eax
这个好像是控制不了的,可能与COFF转OMF的过程有关,所以现在我已经打算放弃CB了,还是用VC省心
爱蹄子的羊头 2013-02-01
  • 打赏
  • 举报
回复
引用 8 楼 dataxdata 的回复:
引用 6 楼 warrially 的回复:引用 5 楼 dataxdata 的回复:CB有时就出这样的问题,不行就再用一个DLL封装一下 这个方法可以. 不过已经是下下策了.. 有没有更好的解决办法啊? 我也碰到过几次这样的事情,都是自己用VC再做个DLL重新封装,也不是很麻烦,如果原DLL的输出函数很多很复杂的话,可以把一部分业务逻辑也封装进去,简化调用接……
输出函数略多了些. 我在汇编里面看C++Builder 多压了一个参数进去. 不知道他为什么要这么做. VC 里面是 push5次 CB push5次以后 又push 了一次 eax
dataxdata 2013-02-01
  • 打赏
  • 举报
回复
引用 6 楼 warrially 的回复:
引用 5 楼 dataxdata 的回复:CB有时就出这样的问题,不行就再用一个DLL封装一下 这个方法可以. 不过已经是下下策了.. 有没有更好的解决办法啊?
我也碰到过几次这样的事情,都是自己用VC再做个DLL重新封装,也不是很麻烦,如果原DLL的输出函数很多很复杂的话,可以把一部分业务逻辑也封装进去,简化调用接口;如果简单的话,就直接封装成个warpper就行了
爱蹄子的羊头 2013-02-01
  • 打赏
  • 举报
回复
引用 3 楼 Behard 的回复:
两个问题: 1. 在 dll 和 exe 中都应该指定调入方式,如 WINAPI (也就是__stdcall) extern "C" __declspec(dllexport) IMpkManip* __stdcall createMpkManip(); 2. 一般不要跨开发工具导出类指针,而是导出标准函数,如 int, unsigned char 等 ……
DLL 是第三方的. 不开源..
爱蹄子的羊头 2013-02-01
  • 打赏
  • 举报
回复
引用 5 楼 dataxdata 的回复:
CB有时就出这样的问题,不行就再用一个DLL封装一下
这个方法可以. 不过已经是下下策了.. 有没有更好的解决办法啊?
dataxdata 2013-01-31
  • 打赏
  • 举报
回复
CB有时就出这样的问题,不行就再用一个DLL封装一下
Behard 2013-01-31
  • 打赏
  • 举报
回复
调用约定: __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
Behard 2013-01-31
  • 打赏
  • 举报
回复
两个问题: 1. 在 dll 和 exe 中都应该指定调入方式,如 WINAPI (也就是__stdcall) extern "C" __declspec(dllexport) IMpkManip* __stdcall createMpkManip(); 2. 一般不要跨开发工具导出类指针,而是导出标准函数,如 int, unsigned char 等
爱蹄子的羊头 2013-01-31
  • 打赏
  • 举报
回复



左边是 VC 的demo 右边是 C++Builder 的 demo

求大神帮忙看一下.
爱蹄子的羊头 2013-01-31
  • 打赏
  • 举报
回复
在 OllyDbg 里面下断点后发现 VC 调用的参数是正常的 C++Builder 调用的 ("c:\\1.txt") 变成了第二个参数 // 是调用约定的问题吗? 应该都是 cdecl才对啊?

13,870

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder相关内容讨论区
社区管理员
  • 基础类社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧