求助高手们,C#封送接口到Dll

swjtulgj 2010-08-25 11:01:12
C#接口。
[ComImport, Guid("7C587563-4F3C-45cb-8ECD-6AE604D0527D"), InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
[ComVisible(true)]
public interface INotifyCallback
{
void MyEventCallback(int nMSG);
void MyEventCallback2(int nMSG);
。。。
}

上面是C#接口,我想实现的是将这个接口的一个实例当做参数传递给Dll,实现回调。

C代码中定义了一个类似的接口,
interface INotifyCallback
{
virtual void __stdcall MyEventCallback(int nMSG);
virtual void __stdcall MyEventCallback2(int nMSG);
     。。。
};


可是交给C的DLL去处理这个接口时,一调用接口的方法就会崩溃。。。。
恼火啊。
急切,,谢啦。
...全文
245 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
swjtulgj 2010-09-13
  • 打赏
  • 举报
回复
回调是监听到事件后回调,脱离了线程就没有啥用处了,艾
swjtulgj 2010-09-13
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 gomoku 的回复:]
引用楼主 swjtulgj 的回复:
C代码中定义了一个类似的接口,
interface INotifyCallback
{
virtual void __stdcall MyEventCallback(int nMSG);
virtual void __stdcall MyEventCallback2(int nMSG);
};……

你C#中定义为IDispatch,而C中却是……
[/Quote]

现把分给你啦。
回调一般是注册到线程里面去, 可是线程里面一调用就崩溃了.
注册的时候还没起线程,这时候直接调用回调就没有问题。 如下:

int CCommunication::RegisterEventCallback(IEventCallback* pcb)
{
m_pEventCallback = pcb;
//m_pEventCallback->EventCallback(33); // 可以
//CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)threadfunc, (void*)pcb, 0, NULL); //不行
return 0;
}

不知道是为啥了。。
gomoku 2010-08-28
  • 打赏
  • 举报
回复
[Quote=引用楼主 swjtulgj 的回复:]
C代码中定义了一个类似的接口,
interface INotifyCallback
{
virtual void __stdcall MyEventCallback(int nMSG);
virtual void __stdcall MyEventCallback2(int nMSG);
};……
[/Quote]
你C#中定义为IDispatch,而C中却是一个光秃秃的接口,两个接口的布局完全不同了。
C#的INotifyCallback相当于IUnknow,紧跟着IDispatch,再跟着MyEventCallback;你在C调用第一个函数,等于调用到IUnknown的QueryInterface。

建议C和C#的接口都继承IUnknown或IDispatch:

interface INotifyCallback : IDispatch  //<---
{
virtual void __stdcall MyEventCallback(int nMSG);
virtual void __stdcall MyEventCallback2(int nMSG);
};
extern "C"
{
_declspec(dllexport) VOID _stdcall RegNotify(INotifyCallback* p)
{
p->MyEventCallback(123);
}
}


[ClassInterface(ClassInterfaceType.None)]
public partial class Form1 : Form, INotifyCallback
{
public Form1()
{
InitializeComponent();
RegNotify(this);
}
public void MyEventCallback(int nMSG) { MessageBox.Show("hello" + nMSG); }
public void MyEventCallback2(int nMSG){}

[DllImport("Mydll.dll")]
static extern bool RegNotify([MarshalAs(UnmanagedType.Interface)]INotifyCallback a);

}
[InterfaceType( ComInterfaceType.InterfaceIsIDispatch)] //<---
interface INotifyCallback
{
void MyEventCallback(int nMSG);
void MyEventCallback2(int nMSG);
}
swjtulgj 2010-08-28
  • 打赏
  • 举报
回复
还有人知道不?为啥会不能用呢
swjtulgj 2010-08-25
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 bloodish 的回复:]
如果是这样的话,暂时想不到最佳的方法了.

实在无法让C++代码回调,就尝试在C#这边开线程轮询等待消息.
轮询的方式可以是让C++通过Event通知消息,C#这边WaitForSingleObject等待Event被Set,然后去接收消息.

WaitForSingleObject,这个是CE上面Coredll.dll里的系统函数,需要做PInvoke.
[/Quote]


这也是个好办法,高手啊~~~~~
我再尝试着弄弄,实在不行就采取这个方式了。。好麻烦呀,
bloodish 2010-08-25
  • 打赏
  • 举报
回复
如果是这样的话,暂时想不到最佳的方法了.

实在无法让C++代码回调,就尝试在C#这边开线程轮询等待消息.
轮询的方式可以是让C++通过Event通知消息,C#这边WaitForSingleObject等待Event被Set,然后去接收消息.

WaitForSingleObject,这个是CE上面Coredll.dll里的系统函数,需要做PInvoke.
swjtulgj 2010-08-25
  • 打赏
  • 举报
回复
Marshal.GetFunctionPointerForDelegate Method
Silverlight Other Versions .NET Framework 4.NET Framework 3.5.NET Framework 3.0.NET Framework 2.0
This type has a SecurityCriticalAttribute attribute, which restricts it to internal use by the .NET Framework for Silverlight class library. Application code that uses any member of this type throws a MethodAccessException.
[SECURITY CRITICAL]

Converts a delegate into a function pointer callable from unmanaged code.


呵呵,这个方法限定了内部使用,wince 不得行。。
swjtulgj 2010-08-25
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 bloodish 的回复:]
IntPtr funcPointer1 = Marshal.GetFunctionPointerForDelegate(del1);
GC.KeepAlive(del1);//不是funcPointer11
IntPtr funcPointer2 = Marshal.GetFunctionPointerForDelegate(del2);
GC.KeepAlive(del2);
[/Quote]

复制的你的代码,运行就会有这个异常。 在GetFunctionPointerForDelegate的时候就异常了, Methodaccessexception,应该是手机上不支持??
bloodish 2010-08-25
  • 打赏
  • 举报
回复
IntPtr funcPointer1 = Marshal.GetFunctionPointerForDelegate(del1);
GC.KeepAlive(del1);//不是funcPointer11
IntPtr funcPointer2 = Marshal.GetFunctionPointerForDelegate(del2);
GC.KeepAlive(del2);
bloodish 2010-08-25
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 swjtulgj 的回复:]
引用 4 楼 bloodish 的回复:
碰到类似的情况,一般建议用C++/CLI实现中间层,否则直接想在C#和C++之间交互会有些麻烦.
你不能直接传对象,只能单个设置函数指针.

C# code

public delegate void CallbackDelegate(int msg);
public interface INotifyCallback
{
……


……
[/Quote]

Sorry,忘了两句关键的,你要让GC保证不去回收两个委托,另外Compact Framework是支持的.

IntPtr funcPointer1 = Marshal.GetFunctionPointerForDelegate(del1);
GC.KeepAlive(funcPointer1);
IntPtr funcPointer2 = Marshal.GetFunctionPointerForDelegate(del2);
GC.KeepAlive(funcPointer2);
swjtulgj 2010-08-25
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 bloodish 的回复:]
碰到类似的情况,一般建议用C++/CLI实现中间层,否则直接想在C#和C++之间交互会有些麻烦.
你不能直接传对象,只能单个设置函数指针.

C# code

public delegate void CallbackDelegate(int msg);
public interface INotifyCallback
{
……
[/Quote]


IntPtr funcPointer1 = Marshal.GetFunctionPointerForDelegate(del1);
这句会有个System.MethodAccessException
Attempt to access the method failed.

我这个是wince 平台,呵呵,,
bloodish 2010-08-25
  • 打赏
  • 举报
回复
碰到类似的情况,一般建议用C++/CLI实现中间层,否则直接想在C#和C++之间交互会有些麻烦.
你不能直接传对象,只能单个设置函数指针.

public delegate void CallbackDelegate(int msg);
public interface INotifyCallback
{
void MyEventCallback(int nMSG);
void MyEventCallback2(int nMSG);
}
public class Test : INotifyCallback
{

#region INotifyCallback Members

public void MyEventCallback(int nMSG)
{

}

public void MyEventCallback2(int nMSG)
{

}

#endregion
}

static void Main(string[] args)
{
INotifyCallback inc = new Test();
CallbackDelegate del1 = inc.MyEventCallback;
CallbackDelegate del2 = inc.MyEventCallback2;

IntPtr funcPointer1 = Marshal.GetFunctionPointerForDelegate(del1);
IntPtr funcPointer2 = Marshal.GetFunctionPointerForDelegate(del1);

PhoneLib.RegNotify1(funcPointer1);
PhoneLib.RegNotify2(funcPointer2);
}
swjtulgj 2010-08-25
  • 打赏
  • 举报
回复
简单点,说白了就是传个对象过去给DLL,让DLL调用这个对象的方法。 哎,难倒传过去之后,DLL不能正确识别到对象的函数指针??
swjtulgj 2010-08-25
  • 打赏
  • 举报
回复
我是这样把接口的实例传过去的。

这是一个实现类。
public class Test : INotifyCallback
{
public void MyEventCallback(int nMSG)
{
MessageBox.Show("call back la");
}
     。。。。。。。
     。。。。
}
这个是把接口实例传过去。。 其中 PhoneLib 是我从dll内部获取到的接口。
PhoneLib.RegNotify(new Test());

110,590

社区成员

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

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

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