[英]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包裝器。
要完成任務,有幾個先決條件。
假設您的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.