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

时间:2012-09-20 08:56:35

标签: c# c++ dll dllimport dllexport

下面是我的c ++ DLL

// DLL.cpp : Defines the exported functions for the DLL application.
#include "stdafx.h"
//#include <stdexcept> 
#include<iostream>
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()

为什么我得到这个?

3 个答案:

答案 0 :(得分:1)

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

  1. 您使用C ++或C编写了dll。

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

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

  4. 您的原生DLL

    <强> MyDll.cpp

    #include "stdafx.h"
    
    #include<iostream>
    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

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

答案 1 :(得分:0)

很可能是你的代表

fPointer abc = new fPointer(ping);

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

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

答案 2 :(得分:0)

我需要做的就是...... 只是声明我的代表是......

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