在C#中包装C ++类DLL

时间:2015-02-05 08:13:22

标签: c# c++ dll

我必须在新的C#项目中使用C ++现有代码。此C ++代码是DLL中包含的非托管代码。我的一位同事已经用" C"代码,但在我的情况下,我的DLL包含一个" Class"我不知道是否可以这样做。

在我的C#应用​​程序中使用此C ++类的正确方法是什么?

更新

感谢所有的论文答案。我按照这篇文章Using Unmanaged C Libraries DLLS in NET Application

尝试了一个简单的课程

我的初始课程是在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 个答案:

答案 0 :(得分:1)

我可以提出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你的课程:

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

c)编写一个创建YourClass实例的C ++函数,从DLL中导出并为其编写DllImport包装。

答案 1 :(得分:0)

完成任务有几个先决条件。

  1. 你必须知道文件所在的位置。
  2. 您必须为您要拨打的方法打开签名。
  3. 假设您的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));
        }
    }
    

    P.S:您可以在Dynamic Invoke C++ DLL function in C#

    找到原始代码