繁体   English   中英

如何为非托管C DLL创建C ++ \\ CLI包装器

[英]how to create a c++\cli wrapper for unmanaged c dll

我可能使自己感到困惑,但之前从未做过,有些指导会很有帮助。
我正在尝试从C#应用程序调用一些C代码。 我尝试使用PInvoke但发现它有些棘手。 我以为我会尝试做一个C++\\CLI包装器。

有些复杂的结构具有可变长度的双精度数组,而PInvoke很难处理。
我已经阅读了一些有关如何完成此操作的信息,但我无法弄清楚。 我发现的大多数内容都与包装C++而不是C C代码已经在导出其功能,该功能已经可以从Java应用程序及其JNA服务中使用。 我拥有C代码,标头,库和dll,但宁愿不对任何现有内容进行更改,以免影响其他消耗性应用程序。 调用它的C#应用程序将是64位,大多数示例都在创建win32库,这有关系吗?

更新:在下面添加代码:
注意:这只是几个功能之一,可能是最简单的功能,但是它们都非常相似。

C HEADER:
typedef struct myStruct_t
{
    double prefix[8];
    int length;
    double array[1];
}
myStruct;

C:
extern "C" __declspec( dllexport ) myStruct *doSomething(const myStruct *input, double a)
{
    myStruct *output;
    //doSomething
    return output;
}

包装C和C ++之间几乎没有什么区别。 您需要制作一个C ++ / CLI类库。 然后,在托管C ++ ref类中编写包装本地代码的函数。

例如,假设DLL导出此函数:

int sqr(int x)

然后在类库中包含头文件:

#include <mynativelibrary.h>

您还需要将导入库提供给链接器。

然后,您可以公开该功能。 最简单的方法是将函数包装为ref类的静态方法。 例如:

public ref class Class1
{
public:
    static int sqr(int x)
    {
        return ::sqr(x);
    }
};

然后,您可以像其他任何程序集一样在C#代码中使用此程序集。

我在VisualStudio 2012中创建了一些项目,该项目使用托管代码包装了旧的MFC dll。 我这样做是这样的:

  1. 在CLR中创建一个类库。
  2. 将旧项目链接到新项目
  3. 在新项目中为函数和结构创建包装器,然后调用旧代码。
  4. 在C#代码中使用新对象。

请不要忘记为托管的C ++代码创建单元测试。 (我总是忘记... :)

祝好运。

如果Java可以通过jna调用C代码,那么通过PInvoke使用C#应该不会有问题。 虽然C ++互操作(使用C ++ / Cli)是PInvoke(隐式PInvoke)的一种类型,但使用DllImport却是显式PInvoke。

当您不需要指定如何编组函数参数或显式调用DllImportAttribute时可以指定的任何其他详细信息,但是您需要创建一个附加的C ++ / CLI Dll时,隐式PInvoke很有用。

两种方式都必须将元数据本机数据类型处理为可管理的本机数据类型,这是不可避免的且痛苦的。

在C#中,该结构可以声明为:

[StructLayout(LayoutKind.Sequential)]
    public struct myStruct {
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
        double prefix[] intersects;

        public int length;

        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
        public double[] array;
    }

但是对于该函数,DLLImport无法处理这种情况,因为C#无法删除该函数返回的非托管指针的内存,您可以在C中创建另一个包装函数,使其使用out参数返回结果,在这种情况下,C#代码为:

[DllImport("...")]
    public static extern void doSomething([In, Out] myStruct[] results,  myStruct[] input,  int len);

或者,您可以使用C ++ / CLI互操作,因为它可以处理本机类型和管理类型,因此调用顺序为:

  1. C#代码使用托管数据类型调用此C ++ / CLI函数:

    ManagedmyStruct [] doSomething(ManagedmyStruct []输入,双精度a)

  2. 在C ++ / CLI函数domSomething中,它调用本机函数,步骤为:

    ManagedmyStruct [] doSomething(ManagedmyStruct [] input,double a){

      //convert the ManagedmyStruct[] input to native type myStruct* input myStruct ret* = doSomething(input, a); //convert ret to managed type ManagedmyStruct[] rets return rets; 

    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM