1

下面是我的 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 的输出,但程序最后因为以下执行而崩溃

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()

为什么我得到这个?

4

3 回答 3

1

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

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

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

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

您的本机 DLL

我的DLL.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 库,本机 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);
}

使用本机 DLL 的 C# 代码

程序.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

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

于 2012-09-21T01:23:44.420 回答
0

很可能是您的代表

fPointer abc = new fPointer(ping);

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

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

于 2012-09-20T09:34:38.203 回答
0

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

[UnmanagedFunctionPointer(CallingConvention.Cdecl)] 
public delegate void MyDelegate(); 
于 2012-09-21T05:39:14.250 回答