xcv*_*cvd 18 .net interop c++-cli c#-4.0
我一直在试验C++/CLI委托(因为我正在尝试创建一个.NET参考库),我遇到了以下问题.
我在C++/CLI中定义委托,然后在C#中创建委托的实例,然后通过非托管C++通过函数指针调用委托的实例.这一切都按预期工作.
代码来说明这一点(首先是我的C#)
using System;
namespace TestProgram
{
class Program
{
static void Main(string[] args)
{
Library.Test.MessageDelegate messageDelegate = new Library.Test.MessageDelegate(Message);
Library.Test test = new Library.Test(messageDelegate);
test.WriteMessage();
Console.Read();
}
static void Message()
{
Console.WriteLine(1024);
}
}
}
Run Code Online (Sandbox Code Playgroud)
接下来我的托管c ++文件(Managed.cpp)
#include "Unmanaged.hpp"
#include <string>
namespace Library
{
using namespace System;
using namespace System::Runtime::InteropServices;
public ref class Test
{
public:
delegate void MessageDelegate();
internal:
MessageDelegate^ Message;
void* delegatePointer;
public:
Test(MessageDelegate^ messageDelegate)
{
delegatePointer = (void*)Marshal::GetFunctionPointerForDelegate(messageDelegate).ToPointer();
}
void WriteMessage()
{
Unmanaged::WriteMessage(delegatePointer);
}
};
}
Run Code Online (Sandbox Code Playgroud)
我的非托管C++文件(Unmanaged.cpp)
#include "Unmanaged.hpp"
namespace Unmanaged
{
typedef void (*WriteMessageType)();
WriteMessageType WriteMessageFunc;
void WriteMessage(void* Function)
{
WriteMessageType WriteMessageFunc = (WriteMessageType)(Function);
WriteMessageFunc();
}
}
Run Code Online (Sandbox Code Playgroud)
此代码全部按预期工作,输出为"1024",因为Method()由指向委托方法的函数指针调用.
尝试使用带有参数的委托应用相同的方法时出现问题,即:delegate void MessageDelegate(int number);
我的代码现在如下(C#):
using System;
namespace AddProgram
{
class Program
{
static void Main(string[] args)
{
Library.Test.MessageDelegate messageDelegate = new Library.Test.MessageDelegate(Message);
Library.Test test = new Library.Test(messageDelegate);
test.WriteMessage(1024);
Console.Read();
}
static void Message(int number)
{
Console.WriteLine(number);
}
}
}
Run Code Online (Sandbox Code Playgroud)
我的托管C++文件:
#include "Unmanaged.hpp"
#include <string>
namespace Library
{
using namespace System;
using namespace System::Runtime::InteropServices;
public ref class Test
{
public:
delegate void MessageDelegate(int number);
internal:
MessageDelegate^ Message;
void* delegatePointer;
public:
Test(MessageDelegate^ messageDelegate)
{
delegatePointer = (void*)Marshal::GetFunctionPointerForDelegate(messageDelegate).ToPointer();
}
void WriteMessage(int number)
{
Unmanaged::WriteMessage(delegatePointer, number);
}
};
}
Run Code Online (Sandbox Code Playgroud)
我的非托管C++文件:
#include "Unmanaged.hpp"
namespace Unmanaged
{
typedef void (*WriteMessageType)(int number);
WriteMessageType WriteMessageFunc;
void WriteMessage(void* Function, int number)
{
WriteMessageType WriteMessageFunc = (WriteMessageType)(Function);
WriteMessageFunc(number);
}
}
Run Code Online (Sandbox Code Playgroud)
当我执行程序时,我收到以下错误:
Unmanaged Library Test.dll中发生未处理的"System.AccessViolationException"类型异常
附加信息:尝试读取或写入受保护的内存.这通常表明其他内存已损坏.
顺便说一句,控制台窗口确实显示1024,但随后是一个随机int(~1000000),然后我得到错误.
我可以开始想象我得到这个错误的一些原因,但我不确定并且很难找到.如果有人能告诉我为什么我会收到这个错误,以及我能做些什么来修复它,我将非常感激.
Han*_*ant 13
void WriteMessage(void* Function, int number)
Run Code Online (Sandbox Code Playgroud)
将函数指针作为void*传递是一个非常糟糕的主意.它可以防止编译器检查你做错了什么.虽然编译器在这种特定情况下无法检测到它,但是有些问题.委托被封送为使用__stdcall调用约定的函数指针,实际的函数指针使用__cdecl调用约定,本机代码的默认值.这导致堆栈在通话中失衡.
您可以通过将[UnmanagedFunctionPointer]属性应用于委托声明来修复它,指定CallingConvention :: Cdecl.
归档时间: |
|
查看次数: |
9379 次 |
最近记录: |