在C#中调用C++ 动态库传入回调函数指针的问题,请大家帮忙!

heartthrob 2008-09-11 12:20:43
程序中有个模块是用C++写的,封装成了 dll文件,接口名称如下:

int Test(LP_TEST_CALL_BACK_FUNC callback)
{
m_gCallBackFun = callback;//保存回调函数指针值
}

要求传入的参数是一个回调函数指针。回调函数的原型要求为:

void testCallBack(BYTE *pData,int nLen)
{
//对pData数据进行处理。
}

//dll里面的函数调用回调函数处理
void dellData()
{
byte data[100];
for(byte i = 0 ;i < 100;i++)
data[i] = i;
//调用C#传入的回调函数处理这些值
m_gCallBackFun(data,100); //问题在此,调用完后出错,此时C#里的回调函数代码已经执行完。
}

上层模块是用C#写的,现在用C#调用testCallBack接口

C#里
[DllImport("Test.dll")]
public static extern void testCallBack(BYTE []data,int nlen);

void Test()
{
testCallBack(testCallBack);
}

void testCallBack(BYTE *pData,int nLen)
{
//对pData数据进行处理。
//......

MessageBox.show("数据执行完毕"); //dll调用回调函数处理时 本对话框已经弹出,数据已经处理完毕!
}

现在的问题是,每次dll里面执行这个回调函数指针,程序都会报错,说什么访问了非法的内存。请问有没有朋友遇到过这种问题?现在焦头烂额,请大家帮忙看看问题出在哪儿?
...全文
921 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
02051104 2010-11-03
  • 打赏
  • 举报
回复
把指针换成IntPtr,不能使用byte【】这种形式,我上次也出现过这种问题的,网上很多说要用数组的形式,其实是不对的,要用IntPtr类型,在到C#这边就行转换就可以了。。
宝_爸 2008-09-12
  • 打赏
  • 举报
回复
还没解决。关注,帮顶。

lz,实在不行我还有一个workaround.

就是在C++端编码,变成可视字符,然后在C#端解码。
例如使用Base64编码成字符串,再在C#端解码变成byte[]
heartthrob 2008-09-11
  • 打赏
  • 举报
回复
不好意思,下面一部分写错了,是这样

程序中有个模块是用C++写的,封装成了 dll文件,接口名称如下:

int RegCallBack(LP_TEST_CALL_BACK_FUNC callback)
{
m_gCallBackFun = callback;//保存回调函数指针值
}

要求传入的参数是一个回调函数指针。回调函数的原型要求为:

void testCallBack(BYTE *pData,int nLen)
{
//对pData数据进行处理。
}

//dll里面的函数调用回调函数处理
void dellData()
{
byte data[100];
for(byte i = 0 ;i < 100;i++)
data[i] = i;
//调用C#传入的回调函数处理这些值
m_gCallBackFun(data,100); //问题在此,调用完后出错,此时C#里的回调函数代码已经执行完。
}

上层模块是用C#写的,现在用C#调用testCallBack接口

C#里
[DllImport("Test.dll")]
public static extern void RegCallBack(BYTE []data,int nlen);

void Test()
{
RegCallBack(testCallBack);
}

void testCallBack(BYTE *pData,int nLen)
{
//对pData数据进行处理。
//......

MessageBox.show("数据执行完毕"); //dll调用回调函数处理时 本对话框已经弹出,数据已经处理完毕!
}

现在的问题是,每次dll里面执行这个回调函数指针,程序都会报错,说什么访问了非法的内存。请问有没有朋友遇到过这种问题?现在焦头烂额,请大家帮忙看看问题出在哪儿?
wenbin 2008-09-11
  • 打赏
  • 举报
回复
用委托试下?
优途科技 2008-09-11
  • 打赏
  • 举报
回复
tianmingl 2008-09-11
  • 打赏
  • 举报
回复
unsafe private int test(byte* data, int nLen)
加个static试一试
heartthrob 2008-09-11
  • 打赏
  • 举报
回复
有没有高手帮帮忙啊? 因为我们有很多个dll模块都是要求传入这样一样类似的函数指针,由模块与其他程序和各种设备进行通讯,然后传给上层的C#程序.以前我用C++写程序就不会有这个问题,怎么换成了C#就这么麻烦.着急呀,老大.
宝_爸 2008-09-11
  • 打赏
  • 举报
回复
Good luck!
宝_爸 2008-09-11
  • 打赏
  • 举报
回复
byte[]也不行,我试过了。暂时没想到好的方法,有一个workaround
就是buffer也是从C#传过去的,然后在dellData中对这个传入的buffer进行操作。

我的测试代码
C++端声明:

typedef int (*LP_TEST_CALL_BACK_FUNC)(char* pData, int nLen);
extern "C" HASP_EXT_API void Test();
extern "C" HASP_EXT_API void SetCallBack(LP_TEST_CALL_BACK_FUNC fp, char* pBuffer, int len);

实现:
LP_TEST_CALL_BACK_FUNC g_fp = NULL;
char* g_pBuffer = NULL;
int g_len = 0;

extern "C" void Test()
{
if (g_fp != NULL)
{
for(char i = 0 ;i < g_len -1;i++)
g_pBuffer[i] = i;

//g_fp(data,len);

}
}

extern "C" void SetCallBack(LP_TEST_CALL_BACK_FUNC fp, char* pBuffer, int len)
{
g_fp = fp;
g_pBuffer = pBuffer;
g_len = len;
}


C#端:
unsafe public delegate int Mydelegate(byte* data, int nLen);

unsafe private int test(byte* data, int nLen)
{
return 1;
}


unsafe private void button1_Click(object sender, EventArgs e)
{
byte[] buffer = new byte[100];
for (int i = 0; i<100; ++i)
{
buffer[i] = 0;
}
Mydelegate pf = new Mydelegate(test);
SetCallBack(pf, buffer, 100);

Test();

}

[DllImport("TestPVCallback.dll")]
public static extern void SetCallBack(Mydelegate fp, byte[] data, int nLen);

[DllImport("TestPVCallback.dll")]
public static extern void Test();
LQknife 2008-09-11
  • 打赏
  • 举报
回复
BYTE *pData这个改成 byte[]看看 要不你去找找c++和c#类型定义表
heartthrob 2008-09-11
  • 打赏
  • 举报
回复
希望有高手能自己写段简单的代码自己测试一下! 3楼的朋友很感谢你,就是那样的写法,但问题没解决呀!
palmax 2008-09-11
  • 打赏
  • 举报
回复
C++的函数指针在C#的DllImport里要声明成委托
heartthrob 2008-09-11
  • 打赏
  • 举报
回复
难道每一个高手弄过吗?痛苦哦。
我用得unsafe语句,没用,跟这个无关。

110,579

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

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