C#调用C++的DLL问题,非常严重,小弟拜谢求解!!!
-------C++的dll代码---------********trydll.cpp****************
// trydll.cpp : 定义 DLL 应用程序的入口点。
//
#include "stdafx.h"
#include "trydll.h"
//BOOL APIENTRY DllMain( HANDLE hModule,
// DWORD ul_reason_for_call,
// LPVOID lpReserved
// )
//{
// return TRUE;
//}
bool APIENTRY abc::hello()
{
MessageBox(NULL,"aaa","third",MB_OK);
return true;
}
**************trydll.h***************
class abc
{
public:
bool APIENTRY hello();
};
*************trydll.def*************
LIBRARY "trydll"
EXPORTS
hello;
---------------C#代码--------------
[DllImport("trydll.dll")]
internal static extern bool hello();
private void Form1_Load(object sender, EventArgs e)
{
hello();
}
运行后首先弹出"aaa"的MessageBox 接着 hello(); 这一行就出现这样的一个错误窗口:
请问这是什么原因造成的?
C#调用C++的DLL,使用哪种方法最好?最好能具体说明,万分感激,小弟拜谢了!!!! --------------------编程问答-------------------- 难道是因为internal? --------------------编程问答-------------------- 此图片仅限于网易用户交流沟通使用!
难道是你和网易的版权问题? --------------------编程问答-------------------- 小弟在网上找了一片文章,做过一个例子,也出现了奇怪的问题,这里贴出来,大家帮忙看看怎么回事?
文章地址:http://blog.csdn.net/Steven_god/archive/2007/12/13/1932798.aspx
----------------C++代码------------------------
// Cdll.cpp : 定义 DLL 应用程序的入口点。
//
#include "stdafx.h"
#ifdef _MANAGED
#pragma managed(push, off)
#endif
// 导出函数,使用“ _stdcall ” 标准调用
extern "C" _declspec(dllexport)int _stdcall count(int init);
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
return TRUE;
}
int _stdcall count(int init)
{//count 函数,使用参数 init 初始化静态的整形变量 S ,并使 S 自加 1 后返回该值
static int S=init;
S++;
return S;
}
#ifdef _MANAGED
#pragma managed(pop)
#endif
----------------------C#代码------------------
[DllImport("Count.dll")]
static extern int count(int init);
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show(" 用 DllImport 调用 DLL 中的 count 函数, \n 传入的实参为 0 ,得到的结果是: " + count(0).ToString(), " 挑战杯 ");
.....
}
将dll生成的Count.dll复制到了C#工程的/bin/Debug/文件夹下,两边编译都没问题,运行后却出现找不到Count.dll模块的错误
这究竟是为什么? 感谢各位大侠解答,谢谢!!! --------------------编程问答-------------------- 大家看不见图吗?我把图片传到网易相册了,但我这里能看见,这样我把错误内容敲出来吧
错误是:检测到PInvokeStackImbalance
对 PInvoke函数“LinkCdll!LinkCDll.Form1::hello“的调用导致堆栈不对称。原因可能是托管的PInvoke签名与非托管的目标签名不匹配。请检查PInvoke签名的调用约定和参数与非托管的目标签名是否匹配。 --------------------编程问答-------------------- To qthai :
不是internal的原因,我去掉也一样 --------------------编程问答-------------------- 关注中,顶~!!!!!!!!! --------------------编程问答-------------------- 顶一下 --------------------编程问答-------------------- 顶起来,希望能得到更多高手的关注!!! --------------------编程问答-------------------- 不知道你用的什么环境编译的,你的代码我用VC6编译DLL,VS 2003调用,没问题,不出错的。
DLL你可能是2005编译的吧,可能差异在这里,你不要编译托管的DLL试试看。 --------------------编程问答-------------------- To ezsea :
你编译的是我的那一楼的代码?顶楼的还是3楼的?
我确实是在2005中试验的,2005编译dll,2005调用,
但是我编译dll时创建的是win32的dll,并且编译选项是无clr支持的,应该是非托管的 --------------------编程问答-------------------- 我觉得应该在C++的Dll头文件中加上
extern "C" _declspec(dllexport)int _stdcall hello(); 这样的说明。
至于C#程序运行后却出现找不到Count.dll模块的错误,这可能是引用的路径不对,改成[DllImport("C:\\test\Count.dll")]这样的绝对路径试试。
--------------------编程问答-------------------- 我编译的是你3楼的,呵呵,我是没编出问题啦 --------------------编程问答-------------------- To dk385 :
你说的这种方法我试过,这个实际上和添加一个.def文件2种做法是取其一的,并且我试过错误情况一样。
另外改为绝对路径后确实不是找不到模块了,但是却出现加载模块的错误,不知你是否可以在你机器上试一下,如果没问题的话,那真是我的环境有问题了?
To ezsea :
我没有装VC6,如果真的跟环境有关系的话那还真是有意思了,呵呵
谢谢大家的关注,希望继续讨论!! --------------------编程问答-------------------- 对PInvoke函数“LinkCdll!LinkCDll.Form1::hello“的调用导致堆栈不对称。原因可能是托管的PInvoke签名与非托管的目标签名不匹配。请检查PInvoke签名的调用约定和参数与非托管的目标签名是否匹配。
从这里来看,如果排除了C#参数与DLL的参数不一致的情况,可能就是调用约定不一致或字符集不一致。
可以这样试下:
[DllImport("C:\\test\\Count.dll", CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall)]
[DllImport("C:\\test\\Count.dll", CharSet=CharSet.Ansi, CallingConvention=CallingConvention.Cdecl)]
1. 用__stdcall,栈的清除工作是由函数自己解决清除工作,
2 用 _cdecl, 栈的清除工作是由调用者来完成的。
--------------------编程问答-------------------- dll不要输出类函数
--------------------编程问答-------------------- 顶起,希望得到更多高手的解答,谢谢!!
补充:.NET技术 , C#