未处理的exception:System.AccessViolationException:尝试读取或写入

下面是我的c ++ DLL

// DLL.cpp : Defines the exported functions for the DLL application. #include "stdafx.h" //#include  #include using namespace std; typedef void (*FunctionPtr)(int); void (*FunctionPtr1)(int); extern "C" __declspec(dllexport)void Caller(); extern "C" __declspec(dllexport)void RegisterFunction(FunctionPtr func_ptr); extern void Caller() { int i = 10; FunctionPtr1(i); } extern void RegisterFunction(FunctionPtr func_ptr1) { FunctionPtr1 = func_ptr1; } 

这个DLL将从c#引用函数名称并将参数传递给c#函数。这是我的c#代码

 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.InteropServices; namespace test { class Program { [DllImport("C:/Users/10602857/Documents/Visual Studio 2010/Projects/DLL/Debug/DLL.dll", CallingConvention = CallingConvention.Cdecl)] public static extern void Caller(); [DllImport("C:/Users/10602857/Documents/Visual Studio 2010/Projects/DLL/Debug/DLL.dll", CallingConvention = CallingConvention.Cdecl)] public static extern fPointer RegisterFunction(fPointer aa); static void Main(string[] args) { Console.WriteLine("DLL Linking"); fPointer abc = new fPointer(ping); RegisterFunction(abc); //send address of function to DLL Caller(); //call from DLL } public delegate void fPointer(int s); // point to every functions that it has void as return value and with no input parameter public static void ping(int a) { Console.WriteLine("ping executed " + a); } public static void add1() { Console.WriteLine("add executed"); } } } 

c#代码能够获得我在c ++ dll中使用的值,如下所示

 int i = 10; FunctionPtr1(i); 

M获得了sedired输出,但是progrram最后因为执行而崩溃了

 Unhandled Exception: System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt. at test.Program.Caller() 

为什么我得到这个?

好的,我为你编写了测试代码。 概念很简单。

  1. 你用C ++或C写了dll。

  2. CLR库(Managed dll)包装你的dll。

  3. 您的C#代码可以通过CLR库使用您的本机DLL。

你的原生DLL

MyDll.cpp

 #include "stdafx.h" #include using namespace std; typedef void (*FunctionPtr)(int); void (*FunctionPtr1)(int); extern "C" __declspec(dllexport)void Caller(); extern "C" __declspec(dllexport)void RegisterFunction(FunctionPtr func_ptr); extern void Caller() { int i = 10; FunctionPtr1(i); } extern void RegisterFunction(FunctionPtr func_ptr1) { FunctionPtr1 = func_ptr1; } 

您的CLR库,Native Dll的包装器

MyDllCLR.h

 #pragma once using namespace System; using namespace System::Runtime::InteropServices; typedef void (*FunctionPtr2)(int); extern "C" __declspec(dllimport)void Caller(); extern "C" __declspec(dllimport)void RegisterFunction(FunctionPtr2 func_ptr); namespace MyDllCLR { void MyFunc(int i); public ref class Class { public: delegate void FunctionDelegate(int i); static FunctionDelegate^ fun; static void Caller1() { Caller(); } static void RegisterFunction1(FunctionDelegate^ f) { fun = f; // Wrapper MyFunc call this delegate // this occurs runtime error and I don't know why. // So I wrote Warpper MyFunc() method. I usually do like this. //IntPtr p = Marshal::GetFunctionPointerForDelegate(fun); //RegisterFunction((FunctionPtr2)(void*)p); // Register Function Wrapper instead of user delegate. RegisterFunction(MyFunc); } }; } 

MyDllCLR.cpp

 #include "stdafx.h" #include "MyDllCLR.h" void MyDllCLR::MyFunc(int i) { MyDllCLR::Class::fun(i); } 

使用Native DLL的C#代码

Program.cs中

 using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace TestMyDllCLR { class Program { static void MyFunc(int i) { Console.WriteLine("Come on! {0}", i); } static void Main(string[] args) { MyDllCLR.Class.RegisterFunction1(MyFunc); MyDllCLR.Class.Caller1(); } } } 

Program.cs需要Native DLL和CLR DLL

当然,这不是实现目标的唯一途径。 🙂

很可能是你的代表

 fPointer abc = new fPointer(ping); 

在使用之前收集垃圾。 您需要将对委托的引用存储为类的字段,以确保它在类的生命周期中存活。

尝试在main之外定义fPointer abc然后在main为它分配new fPointer(ping) ,看看是否有帮助。

我需要做的只是…宣布我的代表为……

 [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate void MyDelegate();