簡體   English   中英

在C#中包裝C ++類DLL

[英]Wrap C++ class DLL in C#

我必須在新的C#項目中使用C ++現有代碼。 此C ++代碼是DLL中包含的非托管代碼。 我的一位同事已經使用“ C”代碼完成了此操作,但就我而言,我的DLL包含“類”,我不知道是否可以這樣做。

在我的C#應用​​程序中使用此C ++類的正確方法是什么?

更新:

感謝所有這些答案。 我嘗試通過遵循本文在NET應用程序中使用非托管C庫DLLS的簡單類來完成此操作

我的初始班級是在Borland C ++ Builder 6上編碼的:

TEST.CPP:

#include <basepch.h>
#pragma hdrstop
#include "Test.h"
#pragma package(smart_init)

__fastcall TTest::TTest() {
        //rien
}
__fastcall TTest::~TTest() {
        //rien
}
void __fastcall TTest::setNombre(int nbr) {
        nombre = nbr;
}
int __fastcall TTest::getNombre() {
        return nombre;
}

Test.h:

#ifndef TestH
#define TestH
#include <SysUtils.hpp>
#include <Classes.hpp>
#include <string.h>
#include <stdio.h>
#include <StrUtils.hpp>
#include <time.h>

class PACKAGE TTest
{
private:
       int nombre;
protected:
public:
        __fastcall TTest();
        __fastcall ~TTest();
        void __fastcall setNombre(int nbr);
        int __fastcall getNombre();
};
extern PACKAGE TTest *Test;
#endif

此類的編譯可以:D

然后,我嘗試像本文中一樣創建非托管類。 但是我在C ++ Builder中創建此類時遇到問題。

Unmanaged.cpp:

#pragma hdrstop
#include "Unmanaged.h"
#pragma package(smart_init)

struct UnmanagedClasseTest
{
        int nombre;

        [DllImport("ClasseTest.dll", EntryPoint="@TTest@$bctr$qqrv", CallingConvention=CallingConvention::ThisCall)]
        static void ctor(UnmanagedClasseTest* c);

        [DllImport("ClasseTest.dll", EntryPoint="@TTest@$bdtr$qqrv", CallingConvention=CallingConvention::ThisCall)]
        static void dtor(UnmanagedClasseTest* c);

        [DllImport("ClasseTest.dll", EntryPoint="@TTest@setNombre$qqri", CallingConvention=CallingConvention::ThisCall)]
        static void setNombre(UnmanagedClasseTest* c, int nbr*);

        [DllImport("ClasseTest.dll", EntryPoint="@TTest@getNombre$qqrv", CallingConvention=CallingConvention::ThisCall)]
        static int getNombre(UnmanagedClasseTest* c);

        static void Uctor(UnmanagedClasseTest* c) {
                ctor(c);
        }
        static void Udtor(UnmanagedClasseTest* c) {
                dtor(c);
        }
        static void UsetNombre(UnmanagedClasseTest* c, int i) {
                nombre = setNombre(c);
        }
        static int UgetNombre(UnmanagedClasseTest* c) {
                return getNombre(c);
        }
};

Unmanaged.h:

#ifndef UnmanagedH
#define UnmanagedH

static void ctor(UnmanagedClasseTest* c);
static void dtor(UnmanagedClasseTest* c);
static void setNombre(UnmanagedClasseTest* c, int nbr*);
static int getNombre(UnmanagedClasseTest* c);
static void Uctor(UnmanagedClasseTest* c);
static void Udtor(UnmanagedClasseTest* c);
static void UsetNombre(UnmanagedClasseTest* c, int i);
static int UgetNombre(UnmanagedClasseTest* c);

#endif

當我要編譯此非托管類時,出現以下錯誤:/

[C++ Erreur] Unmanaged.h(6): E2147 'UnmanagedClasseTest' ne peut pas démarrer une déclaration de parameter

[C++ Erreur] Unmanaged.h(7): E2147 'UnmanagedClasseTest' ne peut pas démarrer une déclaration de parameter

[C++ Erreur] Unmanaged.h(8): E2451 Symbole 'UnmanagedClasseTest' non define

[C++ Erreur] Unmanaged.h(9): E2147 'UnmanagedClasseTest' ne peut pas démarrer une déclaration de parameter

[C++ Erreur] Unmanaged.h(10): E2147 'UnmanagedClasseTest' ne peut pas démarrer une déclaration de parameter

[C++ Erreur] Unmanaged.h(11): E2147 'UnmanagedClasseTest' ne peut pas démarrer une déclaration de parameter

[C++ Erreur] Unmanaged.h(12): E2147 'UnmanagedClasseTest' ne peut pas démarrer une déclaration de parameter

[C++ Erreur] Unmanaged.h(13): E2147 'UnmanagedClasseTest' ne peut pas démarrer une déclaration de parameter

[C++ Erreur] Unmanaged.cpp(17): E2040 Déclaration terminée incorrectement

[C++ Erreur] Unmanaged.cpp(20): E2040 Déclaration terminée incorrectement

[C++ Erreur] Unmanaged.cpp(23): E2040 Déclaration terminée incorrectement

[C++ Erreur] Unmanaged.cpp(26): E2040 Déclaration terminée incorrectement

[C++ Erreur] Unmanaged.cpp(30): E2034 Impossible de convertir 'UnmanagedClasseTest *' en 'int *'

[C++ Erreur] Unmanaged.cpp(30): E2342 Mauvaise correspondance de type dans le paramètre 'c' ('int *' désiré, 'UnmanagedClasseTest *' obtenu)

[C++ Erreur] Unmanaged.cpp(33): E2034 Impossible de convertir 'UnmanagedClasseTest *' en 'int *'

[C++ Erreur] Unmanaged.cpp(33): E2342 Mauvaise correspondance de type dans le paramètre 'c' ('int *' désiré, 'UnmanagedClasseTest *' obtenu)

[C++ Erreur] Unmanaged.cpp(36): E2268 Appel à une fonction non définie 'setNombre'

[C++ Erreur] Unmanaged.cpp(36): E2231 Le membre UnmanagedClasseTest::nombre ne peut pas être utilisé sans un objet

[C++ Erreur] Unmanaged.cpp(39): E2034 Impossible de convertir 'UnmanagedClasseTest *' en 'int *'

[C++ Erreur] Unmanaged.cpp(39): E2342 Mauvaise correspondance de type dans le paramètre 'c' ('int *' désiré, 'UnmanagedClasseTest *' obtenu)

我可以提出2個解決方案。 (1)通過標記__declspec(dllexport)導出整個C ++。 它的所有方法都將從帶有某些錯誤名稱的DLL中導出。 找到這些名稱(例如,通過Depends實用程序),然后用C#代碼編寫DllImport包裝器。

(2)在您的課程中實現基本的COM功能並使用COM interop 最小動作集:

a)實現IUnknown和IMarshal方法:

class YourClass: public IMarshal
{
  // override AddRef, Release, QueryInterface and Marshal here
  ...

  int __declspec(stdcall) foo(int x);
}

b)然后使用C#導入類:

[ComImport, Guid("5BADB572-FE70-4602-8854-E4B461FC5DAE")] 
class YourClass
{ 
  [PreserveSig] int foo(int x);
}

c)編寫一個創建YourClass實例的C ++函數,將其從DLL中導出並為其編寫DllImport包裝器。

要完成任務,有幾個先決條件。

  1. 您必須knpw文件所在的位置。
  2. 您必須為要調用的方法寫簽名。

假設您的dll(mycpp.dll)位於“ c:\\ mycpp.dll”位置,並且有一個名為“ Sum ”的方法,該方法分別采用兩個int參數a和b並返回int。 您可以使用以下代碼:

public class Program
{
    [DllImport(@"c:\mycpp.dll")]

    private static extern int Sum(int a, int b);

    static void Main(string[] args)
    {
        Console.WriteLine(Sum(3,5));
    }
}

PS:您可以在以下位置找到原始代碼: C#中的Dynamic Invoke C ++ DLL函數

暫無
暫無

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

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