C++ 期间出现 NullReferenceException回调 C# 函数
开发商!
我有很奇怪的问题。我的项目有用 C++ 编写的 DLL 和用 C# 编写的 GUI。我已经实现了一些互操作性的回调。我计划在某些情况下 C++ dll 会调用 C# 代码。它有效......但时间不长,我不明白为什么。 C#部分注释中标记的问题
这里是简化示例的完整代码:
C++ DLL:
#include <SDKDDKVer.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
extern "C"
{
typedef void (*WriteSymbolCallback) (char Symbol);
WriteSymbolCallback Test;
_declspec(dllexport) void InitializeLib()
{
Test = NULL;
}
_declspec(dllexport) void SetDelegate(WriteSymbolCallback Callback)
{
Test = Callback;
}
_declspec(dllexport) void TestCall(const char* Text,int Length)
{
if(Test != NULL)
{
for(int i=0;i<Length;i++)
{
Test(Text[i]);
}
}
}
};
C#部分:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
namespace CallBackClient
{
class Program
{
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void WriteToConsoleCallback(char Symbol);
[DllImport("CallbackSketch.dll",CharSet=CharSet.Ansi,CallingConvention=CallingConvention.Cdecl)]
private static extern void InitializeLib();
[DllImport("CallbackSketch.dll",CharSet=CharSet.Ansi,CallingConvention=CallingConvention.Cdecl)]
private static extern void SetDelegate(WriteToConsoleCallback Callback);
[DllImport("CallbackSketch.dll",CharSet=CharSet.Ansi,CallingConvention=CallingConvention.Cdecl)]
private static extern void TestCall(string Text,int Length);
private static void PrintSymbol(char Symbol)
{
Console.Write(Symbol.ToString());
}
static void Main(string[] args)
{
InitializeLib();
SetDelegate(new WriteToConsoleCallback(PrintSymbol));
string test = "Hello world!";
for (int i = 0; i < 15000; i++)
{
TestCall(test, test.Length);// It crashes when i == 6860!!!! Debugger told me about System.NullReferenceException
}
}
}
}
问题是它在第 6860 次迭代时崩溃了!我认为问题是我缺乏这方面的知识。有人可以帮助我吗?
developers!
I have very strange problem. My project has DLL writen in C++ and a GUI writen in C#. And I have implemented callback for some interoperability. I planed that C++ dll will call C# code in some circumstances. It works... but not long and I cant understand why. The problem marked in comment in C# part
Here the complete code of simplified sample:
C++ DLL:
#include <SDKDDKVer.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
extern "C"
{
typedef void (*WriteSymbolCallback) (char Symbol);
WriteSymbolCallback Test;
_declspec(dllexport) void InitializeLib()
{
Test = NULL;
}
_declspec(dllexport) void SetDelegate(WriteSymbolCallback Callback)
{
Test = Callback;
}
_declspec(dllexport) void TestCall(const char* Text,int Length)
{
if(Test != NULL)
{
for(int i=0;i<Length;i++)
{
Test(Text[i]);
}
}
}
};
C# part:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
namespace CallBackClient
{
class Program
{
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void WriteToConsoleCallback(char Symbol);
[DllImport("CallbackSketch.dll",CharSet=CharSet.Ansi,CallingConvention=CallingConvention.Cdecl)]
private static extern void InitializeLib();
[DllImport("CallbackSketch.dll",CharSet=CharSet.Ansi,CallingConvention=CallingConvention.Cdecl)]
private static extern void SetDelegate(WriteToConsoleCallback Callback);
[DllImport("CallbackSketch.dll",CharSet=CharSet.Ansi,CallingConvention=CallingConvention.Cdecl)]
private static extern void TestCall(string Text,int Length);
private static void PrintSymbol(char Symbol)
{
Console.Write(Symbol.ToString());
}
static void Main(string[] args)
{
InitializeLib();
SetDelegate(new WriteToConsoleCallback(PrintSymbol));
string test = "Hello world!";
for (int i = 0; i < 15000; i++)
{
TestCall(test, test.Length);// It crashes when i == 6860!!!! Debugger told me about System.NullReferenceException
}
}
}
}
The problem is that it crashes in 6860th iteration! I believe that the problem is lack of my knowlege in the subject. Could sombody help me?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
是的,这不能正常工作。本机代码正在存储委托对象的函数指针,但垃圾收集器无法看到该引用。就其而言,没有对该对象的引用。下一个集合会毁掉它。轰隆隆。
您必须自己存储对该对象的引用。在类中添加一个字段来存储它:
规则是存储对象的类的生命周期必须至少与本机代码进行回调的机会一样长。在这种特殊情况下它必须是静态的,这是固体的。
Yes, this cannot work properly. The native code is storing a function pointer for the delegate object but the garbage collector cannot see this reference. As far as it is concerned, there are no references to the object. And the next collection destroys it. Kaboom.
You have to store a reference to the object yourself. Add a field in the class to store it:
The rule is that the class that stores the object must have a lifetime at least as long as native code's opportunity to make the callback. It must be static in this particular case, that's solid.