簡體   English   中英

通過托管C ++包裝程序從非托管C ++ dll運行C#函數

[英]Run a C# function from an unmanaged C++ dll through a managed C++ Wrapper

我正在一個C#項目中,該項目使用一些封裝在dll中的非托管C ++代碼。 我必須將該dll作為參考(而不是DllImport)加載,因此我正在編寫托管C ++包裝程序,作為C#和dll之間的橋梁。

我可以輕松地從C#調用dll函數,只需從C#調用包裝中的等效函數,然后從包裝中調用dll函數。 但是,dll中有一些回調函數應調用C#函數,並且該部分不起作用。 我研究了幾種有關這種互操作的教程(stackoverflow,microsoft,codeproject),但是它們已經很老了,我無法使它們工作。

這個想法是dll正在處理實時數據,並且每當dll生成一些結果時,它都應該在Program.cs中調用一個使用這些結果的函數。

我正在處理的代碼非常龐大,因此我做了一個非常簡單的場景,其中包括所有無效的內容。

在Program.cs中,我試圖告訴dll:“進行此功能測試並在完成后調用它”。 然后,為了測試它,我強迫它運行回調函數。 但是我發現了幾個錯誤。

盡管wrapper會編譯並生成wrapper.dll,但是當我在C#項目中加載wrapper.dll時,函數M_setCallback並不存在?

我想知道是否有人可以幫我或給我看一個講解如何做的教程(我發現這些教程沒有我必須使用的3個項目,而且我無法使它們正常工作)。 我嘗試使用委托,但是程序崩潰。

或者,也許有一種更簡單的方法可以做到這一點。

謝謝!

這是代碼,非常簡單:

首先,我有非托管dll :C ++項目,Win32控制台應用程序,已編譯為dll。

defs.h

namespace JJLibrary
{
    typedef void (__stdcall *MYCALLBACK) (bool mybool, int myint);
}

unmanaged_dll.h

#ifndef JJAPI_H
#define JJAPI_H

#ifdef UNMANAGED_EXPORTS
#define JJ_API __declspec(dllexport)
#else
#define JJ_API __declspec(dllimport)
#endif

#include "defs.h"

namespace JJLibrary
{
    JJ_API void U_helloWorld();
    JJ_API void U_setCallback( MYCALLBACK theCallback );
    JJ_API void U_runCallback();
}
#endif //JJAPI_H

unmanaged_dll.cpp

#include "unmanaged_dll.h"
#include <iostream>
using namespace std;

namespace JJLibrary
{

    MYCALLBACK m_callback = 0;

    JJ_API void U_helloWorld()
    {
        cout << "Unmanaged: Hello world" << endl;
    }

    JJ_API void U_setCallback( MYCALLBACK theCallback )
    {
        cout << "Unmanaged: Setting callback" << endl;
        m_callback = theCallback;
    }

    JJ_API void U_runCallback()
    {
        bool b = true;
        int  i = 25;
        cout << "Unmanaged: Running callback: " << b << " " << i << endl;
        if (m_callback)
            m_callback(b, i);
        // In the final application b and i are generated here after processing data, I give them values for testing
        // When they are generated, call the function in C#
    }   

}

包裝: C ++ CLR類項目

包裝器

#include "defs.h"
#include <iostream>

using namespace System;
using namespace System::Runtime::InteropServices;
using namespace JJLibrary;
using namespace std;

namespace wrapper { 

    public ref class Wrapper
    {

    public:

        void M_helloWorld();
        void M_setCallback( MYCALLBACK theCallback );
        void M_runCallback( bool mybool, int myint );

    };
}

包裝器

#include "stdafx.h"
#include "wrapper.h"
#include "defs.h"
#include <iostream>
using namespace wrapper;
using namespace JJLibrary;
using namespace std;

void Wrapper::M_helloWorld()
{
    cout << "Managed: Hello World" << endl;
    U_helloWorld();
}

void Wrapper::M_setCallback( MYCALLBACK theCallback )
{
    cout << "Managed: Setting callback" << endl;
    U_setCallback( theCallback);
}

void Wrapper::M_runCallback(bool mybool, int myint)
{
    cout << "Managed: Running callback" << endl;
    U_runCallback(mybool, myint);
}

最后, Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using wrapper;

namespace CS
{
    class Program
    {

        void Test(bool mybool, int myint)
        {
            Console.WriteLine(!mybool);
            Console.WriteLine(2*myint);
        }


        static void Main(string[] args)
        {
            Wrapper myWrapper = new Wrapper();
            myWrapper.M_helloWorld();
            myWrapper.M_setCallback(Test);
            myWrapper.M_runCallback(true, 25);  // --> false 50

            string s = Console.ReadLine();  // Pause
        }
    }
}

太多的代碼無法真正理解,但是我對類似問題的解決方案涉及一個看起來像這樣的委托。

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void UserFunctionCallback(IntPtr context, int nvalues,
  [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)]IntPtr[] values);

如果有幫助,我可以添加更多代碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM