C++调用DLL(高手请进来解答啊)

zhaoshangjun1987 2011-12-09 04:21:00
比方说我现在有个model.dll,里面有个ADD(),方法,我现在知道需要分别给他传的参数为5 和 demo。 这个2个参数,请问怎么调用这个add()方法,并且将参数传进去。不能设置函数指针,因为我的参数是要写在文件里,再读取到程序,而不是写在程序提前写好。程序里 会动态加载GetProcAddress(),获取函数指针,那怎么给这个指针传参数啊?
...全文
637 35 打赏 收藏 转发到动态 举报
写回复
用AI写文章
35 条回复
切换为时间正序
请发表友善的回复…
发表回复
yisikaipu 2011-12-15
  • 打赏
  • 举报
回复
因直接在release下调试,忽视了栈平衡,修改下代码

顺便说下,这里不适用于直接返回复杂对象的情况,因为入栈处理不同,所以其实仍然没有统一的方法,只不过楼主的情况可能不需要考虑这么全面

struct Para
{
int n; // 参数个数
void* arg[16];
};

void* call(void *p,Para *para)
{
int *re=0;

int n=para->n;
for(int i=0;i<n;++i)
{
void *a=para->arg[n-1-i];
_asm push a // 压地址
}

_asm
{
call p
mov re,eax
}

for(int i=0;i<n;++i)
_asm add esp,4

return re;
}

void* call_val(void *p,Para *para)
{
int *re=0;

int n=para->n;
for(int i=0;i<n;++i)
{
void *a=para->arg[n-1-i];
int x=*(int*)a; // 姑且假设都是32位整型,其它情况类似
_asm push x // 压值
}

_asm
{
call p
mov re,eax
}

for(int i=0;i<n;++i)
_asm add esp,4

return re;
}

int add(int *a,int *b)
{
return *a+*b;
}

int add_val(int a,int b)
{
return a+b;
}

char* sayhello()
{
static char s[]="hello world";
return s;
}

int _tmain(int argc, _TCHAR* argv[])
{
{
void *f=add_val; // 这里你自己去GetProcAddress,然后赋给f
int i=1,j=2;
Para para={2,{&i,&j}};
int re=(int)call_val(f,¶);
cout <<re <<endl;
}

{
void *f=add;
int i=1,j=2;
Para para={4,{&i,&j}};
int re=(int)call(f,¶);
cout <<re <<endl;
}

{
void *f=sayhello;
Para para={0};
char *re=(char*)call(f,¶);
cout <<re <<endl;
}

return 0;
}
zhaoshangjun1987 2011-12-13
  • 打赏
  • 举报
回复
[Quote=引用 32 楼 zhao4zhong1 的回复:]
引用 29 楼 zhaoshangjun1987 的回复:
引用 28 楼 wshjldaxiong 的回复:
这是我在VS2005下的试验。

C/C++ code


int fun3(int n)
{
n++;
return n;
}

int mian()
{
int i;
i = fun3(4);
}



调用反汇编是这样的。

C/C++……
[/Quote]
谢谢,确实 汇编很差,刚才自己调用成功了,呵呵 但去调用第2个就失败了,哎,因为我是这样,push参数进去,然后call调用
__asm
{
push comtrol
}
__asm
{
call addr
mov re,eax
}
不过再按照这个方法去执行第2个 就失败了,谢谢你,我确实应该好看看汇编,呵呵 不然以后调试就麻烦啦。

赵4老师 2011-12-13
  • 打赏
  • 举报
回复
[Quote=引用 29 楼 zhaoshangjun1987 的回复:]
引用 28 楼 wshjldaxiong 的回复:
这是我在VS2005下的试验。

C/C++ code


int fun3(int n)
{
n++;
return n;
}

int mian()
{
int i;
i = fun3(4);
}



调用反汇编是这样的。

C/C++ code


i = fun3(4);
004117……
额 请问参数要以什么方式PUSH进去啊!我对汇编不熟悉,因为我程序读进来都是变量类型的
[/Quote]
亡羊补牢,为时未晚。现在学汇编还来得及。

提醒:
“学习用汇编语言写程序”

“VC调试(TC或BC用TD调试)时按Alt+8、Alt+6和Alt+5,打开汇编窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应内存和寄存器变化,这样过一遍不就啥都明白了吗。
(Linux或Unix下可以在用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。)”
不是一回事!
zhaoshangjun1987 2011-12-13
  • 打赏
  • 举报
回复
[Quote=引用 30 楼 yisikaipu 的回复:]
真有必要搞这么混乱么 :)
[/Quote]

那能提供个好方法么!求教!
yisikaipu 2011-12-13
  • 打赏
  • 举报
回复
真有必要搞这么混乱么 :)
zhaoshangjun1987 2011-12-13
  • 打赏
  • 举报
回复
[Quote=引用 28 楼 wshjldaxiong 的回复:]
这是我在VS2005下的试验。

C/C++ code


int fun3(int n)
{
n++;
return n;
}

int mian()
{
int i;
i = fun3(4);
}



调用反汇编是这样的。

C/C++ code


i = fun3(4);
0041173E pus……
[/Quote]

额 请问参数要以什么方式PUSH进去啊!我对汇编不熟悉,因为我程序读进来都是变量类型的
yisikaipu 2011-12-13
  • 打赏
  • 举报
回复
[Quote=引用 31 楼 zhaoshangjun1987 的回复:]引用 30 楼 yisikaipu 的回复:
真有必要搞这么混乱么 :)


那能提供个好方法么!求教![/Quote]

#6楼就说了,这是设计上的问题

结果你竟然允许用汇编

既然一定要这么搞,问题不是已经解决了么

struct Para
{
int n; // 参数个数
void* arg[16];
};

void* call(void *p,Para *para)
{
int *re=0;

int n=para->n;
for(int i=0;i<n;++i)
{
void *a=para->arg[n-1-i];
_asm push a // 压地址
}

_asm
{
call p
mov re,eax
}

return re;
}

void* call_val(void *p,Para *para)
{
int *re=0;

int n=para->n;
for(int i=0;i<n;++i)
{
void *a=para->arg[n-1-i];
int x=*(int*)a; // 姑且假设都是32位整型,其它情况类似
_asm push x // 压值
}

_asm
{
call p
mov re,eax
}

return re;
}

int add(int *a,int *b)
{
return *a+*b;
}

int add_val(int a,int b)
{
return a+b;
}

char* sayhello()
{
static char s[]="helloworld";
return s;
}

int _tmain(int argc, _TCHAR* argv[])
{
{
void *f=add_val; // 这里你自己去GetProcAddress,然后赋给f
int i=1,j=2;
Para para={2,{&i,&j}};
int re=(int)call_val(f,¶);
cout <<re <<endl;
}

{
void *f=add;
int i=1,j=2;
Para para={4,{&i,&j}};
int re=(int)call(f,¶);
cout <<re <<endl;
}

{
void *f=sayhello;
Para para={0};
char *re=(char*)call(f,¶);
cout <<re <<endl;
}

return 0;
}
小默 2011-12-12
  • 打赏
  • 举报
回复
这是我在VS2005下的试验。

int fun3(int n)
{
n++;
return n;
}

int mian()
{
int i;
i = fun3(4);
}


调用反汇编是这样的。

i = fun3(4);
0041173E push 4
00411740 call @ILT+515(_fun3) (411208h)
00411745 add esp,4
00411748 mov dword ptr [i],eax //返回

希望对楼主有启发。
shayla 2011-12-12
  • 打赏
  • 举报
回复
函数调用后,函数返回值会默认放到eax寄存器里。
可以放到汇编部分之前的局部变量中。
至于怎么得到,如果你对汇编不熟悉的话,可以先用c++写出来。
转成汇编看一下。
例如

33: int i = 0;
00401048 C7 45 FC 00 00 00 00 mov dword ptr [ebp-4],0
34: i = MessageBox(NULL, "test", "test", MB_OK);
0040104F 8B F4 mov esi,esp
00401051 6A 00 push 0
00401053 68 1C 20 42 00 push offset string "test" (0042201c)
00401058 68 1C 20 42 00 push offset string "test" (0042201c)
0040105D 6A 00 push 0
0040105F FF 15 AC A2 42 00 call dword ptr [__imp__MessageBoxA@16 (0042a2ac)]
00401065 3B F4 cmp esi,esp
00401067 E8 34 01 00 00 call __chkesp (004011a0)
0040106C 89 45 FC mov dword ptr [ebp-4],eax


dword ptr [ebp-4]就是int i = 0在栈中的位置。
mov dword ptr [ebp-4],eax
会将返回值附给i
zhaoshangjun1987 2011-12-12
  • 打赏
  • 举报
回复
[Quote=引用 23 楼 shayla 的回复:]
返回值在寄存器eax中
[/Quote]
DWORD dwCurrentVal = 100;
__asm{
// mov EAX,[EBX+120h];
mov dwCurrentVal,eax;

}
我是这样获取的,直接把eax给dwCurrentVal,是否正确啊,谢谢 帮忙看下!
xzj07 2011-12-12
  • 打赏
  • 举报
回复
直接从dll里导出类吧,在定义的时候把参数的默认值设置好就可以了。
zhaoshangjun1987 2011-12-12
  • 打赏
  • 举报
回复
[Quote=引用 23 楼 shayla 的回复:]
返回值在寄存器eax中
[/Quote]
恩 我没获取到,怎么获取啊!请教了
shayla 2011-12-12
  • 打赏
  • 举报
回复
返回值在寄存器eax中
zhaoshangjun1987 2011-12-12
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 wshjldaxiong 的回复:]
引用 18 楼 wshjldaxiong 的回复:
我只知道比较蠢的办法,为那个DLL里的每一个函数都定个指针,留着,想用那个就用哪个。

我觉得这还是可行的,毕竟你从文件中读出了函数名和参数类型之后,本来就会根据信息的不同选择不同的代码来处理的后面的事情,你不妨将它们写成不同的分函数,然后以局部变量的方式定义函数指针。

我想,为每一种情况准备一个处理预案是必须的,因为我们没有办法让代……
[/Quote]

谢谢你 如果我没其他好的解决方案的,我会这样的。呵呵 我最开始也这样,但怕被老板骂!
zhaoshangjun1987 2011-12-12
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 zhao4zhong1 的回复:]
//难道楼主希望
__asm {
push 参数1
push 参数2
call 函数入口
add esp,8 //此句可能应该去掉
}
[/Quote]
刚才我这样是弄成功了,但返回值怎么取到? 在参数2里? 还是怎么回事!求赐教
hengyu654 2011-12-12
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 zhao4zhong1 的回复:]

//难道楼主希望
__asm {
push 参数1
push 参数2
call 函数入口
add esp,8 //此句可能应该去掉
}
[/Quote]

这个貌似应该是
__asm {
push 参数2
push 参数1
call 函数入口
add esp,8 //此句可能应该去掉
}
小默 2011-12-12
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 wshjldaxiong 的回复:]
我只知道比较蠢的办法,为那个DLL里的每一个函数都定个指针,留着,想用那个就用哪个。
[/Quote]
我觉得这还是可行的,毕竟你从文件中读出了函数名和参数类型之后,本来就会根据信息的不同选择不同的代码来处理的后面的事情,你不妨将它们写成不同的分函数,然后以局部变量的方式定义函数指针。

我想,为每一种情况准备一个处理预案是必须的,因为我们没有办法让代码那么智能可以自己处理。
小默 2011-12-12
  • 打赏
  • 举报
回复
我似乎看懂楼主想问什么了,他的意思似乎是说,他的程序已经跑起来了,然后去读了一个文件之后才知道他要调的是DLL里的哪个函数,所以函数指针的类型没办法在写代码的时候就定下。
我只知道比较蠢的办法,为那个DLL里的每一个函数都定个指针,留着,想用那个就用哪个。
或者用void*类型的指针?然后强行使用?不知道行不行,没试过。
shayla 2011-12-12
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 zhaoshangjun1987 的回复:]

我现在举个例子,比方说messagebox,在mode.dll中,参数都为int3个参数:1,2,3, 你要调用成功messagebox这个接口,如果换成了string 2个参数:"1","2"你也要调用成功。怎么办?大侠们,如果是让我修改函数指针的话就算了,我的本意就是不想去修改代码。做个通用的
[/Quote]

如果没有理解错楼主意思的话,可以使用汇编代码:

//先从文件得到各个需要传入的参数
参数压栈:
push param1
push param2
函数指针调用,不需要知道类型
call function
赵4老师 2011-12-12
  • 打赏
  • 举报
回复
//难道楼主希望
__asm {
push 参数1
push 参数2
call 函数入口
add esp,8 //此句可能应该去掉
}
加载更多回复(15)
内容概要:本文围绕面向新能源容量提升的智能软开关(SOP)在配电网重构中的应用展开研究,提出一种基于Matlab的优化模型实现方法。通过引入SOP这一先进电力电子装置,实现对配电网拓扑结构的灵活调控,有效提升分布式新能源(如光伏、风电)的接入能力与消纳水平。研究重点在于构建以降低网络损耗、改善电压质量、提高新能源利用率为目标的配电网重构数学模型,并结合智能优化算法进行求解。文中详细阐述了模型构建思路、辐射状拓扑约束、潮流计算、SOP运行特性建模及求解流程,通过Matlab编程实现仿真验证,充分展示了该方法在提升配电网灵活性与新能源承载能力方面的有效性与实用价值。; 适合人群:具备电力系统分析、优化算法理论基础,熟悉Matlab编程环境,从事新能源并网、主动配电网优化、电力系统规划与运行等领域的研究生、科研人员及工程技术人员。; 使用场景及目标:① 掌握智能软开关(SOP)的工作原理、数学建模及其在配电网中的灵活调控作用;② 学习并实现基于优化算法的配电网动态重构技术,以增强系统对新能源的接纳能力;③ 利用Matlab平台开展电力系统仿真分析,服务于学术研究、毕业设计或实际工程项目的技术验证与方案优化。; 阅读建议:此资源侧重于模型构建与算法实现,建议读者结合Matlab代码深入理解优化模型的建立过程与求解细节,尝试在IEEE标准测试系统(如33节点、69节点系统)上复现结果,并进一步探究不同场景下SOP配置对重构效果的影响,以深化对现代配电网智能化调控技术及其在新型电力系统中关键作用的理解。
内容概要:本文档围绕“风储VSG-基于虚拟同步发电机的风储并网系统Simulink仿真”展开,系统介绍了采用虚拟同步发电机(VSG)控制策略的风电与储能联合并网系统的建模与仿真方法。通过Simulink平台构建完整的电力系统动态模型,重点实现VSG的关键控制逻辑,以提升新能源并网的稳定性、惯性响应与频率支撑能力。文档不仅涵盖核心仿真模型,还整合了大量相关前沿研究内容,如混合储能调频、微电网优化、电动汽车可调能力评估、智能算法在电力系统中的应用等,并提供丰富的Matlab/Simulink代码实例,具有较强的科研复现价值和技术参考意义。; 适合人群:具备电力系统基础理论知识和Matlab/Simulink仿真能力的研究生、科研人员及从事新能源发电、储能控制、智能电网等领域工作的工程技术人员;特别适用于正在开展风储协同控制、虚拟同步机、构网型变流器等相关课题研究的高校师生。; 使用场景及目标:① 深入理解虚拟同步发电机(VSG)在风储并网系统中的控制原理与技术优势;② 借助提供的仿真模型与代码完成科研论文复现、算法验证与系统性能测试;③ 探索新能源高渗透背景下提升电网稳定性的关键技术路径,包括惯量模拟、一次频率响应、储能协同控制等。; 阅读建议:建议读者按照文档结构循序渐进地学习,优先下载并运行配套的Simulink模型与Matlab代码,结合VSG控制策略的设计细节进行调试与分析,同时可关注公众号“荔枝科研社”获取完整资源包及持续的技术支持,以提升科研效率与创新能力。

65,210

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

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