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出力を取得しますが、プログラムは次のexecptionで最後にクラッシュしました

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 ライブラリを介してネイティブ DLL を使用できます。

ネイティブ 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 ライブラリ、ネイティブ 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# コード

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 には、ネイティブ DLL と CLR DLL の両方が必要です。

そしてもちろん、これがあなたの目標への唯一の方法ではありません。:)

于 2012-09-21T01:23:44.420 に答える
0

私がする必要があるのは..私のデリゲートを次のように宣言するだけです...

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

それはあなたの代理人である可能性があります

fPointer abc = new fPointer(ping);

使用される前にガベージコレクションを取得しています。デリゲートへの参照をクラスのフィールドとして保存して、クラスの存続期間中存続するようにする必要があります。

fPointer abc外側を定義してから内側mainに割り当ててみて、それが役立つかどうかを確認してください。new fPointer(ping)main

于 2012-09-20T09:34:38.203 に答える