将非托管c ++类库暴露给c#

时间:2023-01-15 15:45:49

i have in fact two unamaged c++ libraries, one of them makes use of the other. Both are pretty big, so rewriting is not an option for me.

事实上,我有两个未损坏的c ++库,其中一个使用另一个。两者都很大,所以重写对我来说不是一个选择。

I read some stuff about creating a managed c++ library which wraps arround the unmanaged code. But I don't realy get how to get started, and how to combine all this stuff in one Project...

我读了一些关于创建托管c ++库的东西,它围绕非托管代码。但我不知道如何开始,以及如何在一个项目中结合所有这些东西......

are there any step by step guides or good easy to understand examples on how to do this?

有没有一步一步的指南或如何做到这一点的易于理解的例子?

TIA

5 个解决方案

#1


You might consider writing a COM wrapper for your C++ code using ATL. I show how to do this in a blog post. This is how Microsoft exposes functionality that they wrote in C++ (e.g. Windows 7 Libraries features). COM is easily consumed by .NET/C# (see this post). If you go this route, you might consider registration free COM if you don't need to share your wrapper with others.

您可以考虑使用ATL为C ++代码编写COM包装器。我在博客文章中展示了如何做到这一点。这就是Microsoft如何公开他们用C ++编写的功能(例如Windows 7库功能)。 COM很容易被.NET / C#使用(参见这篇文章)。如果你走这条路线,如果你不需要与他人分享你的包装,你可以考虑免注册COM。

#2


You can write managed and unmanaged C++ in the same project. So you can write a wrapper in Managed C++ that calls your native c++ classes etc. Then in C# your managed C++ classes will appear just like any other .net reference. No need to use P/Invoke in this case.

您可以在同一个项目中编写托管和非托管C ++。因此,您可以在Managed C ++中编写一个包装器来调用您的本机c ++类等。然后在C#中,您的托管C ++类将像任何其他.net引用一样出现。在这种情况下无需使用P / Invoke。

#3


you have two options, one is called ijw "it just works" where you can write managed c++ and call unmanaged c++. The other option requires the use of pinvoke.

你有两个选择,一个名为ijw“它只是工作”你可以编写托管c ++并调用非托管c ++。另一种选择需要使用pinvoke。

if you use pinvoke you'll have something like this

如果你使用pinvoke,你会有类似的东西

C#

somefunction("str1", "str2", "str3", "str4"); 

[DllImport(@"myproj.dll", EntryPoint = "somefunction")]
public static extern IntPtr SomeFunction([MarshalAs(UnmanagedType.LPWStr)]string jarg1, [MarshalAs(UnmanagedType.LPWStr)]string jarg2, [MarshalAs(UnmanagedType.LPWStr)]string jarg3, [MarshalAs(UnmanagedType.LPWStr)]string jarg4);

c++

extern "C" __declspec(dllexport) void* __stdcall somefunction(wchar_t * jarg1, wchar_t * jarg2, wchar_t * jarg3, wchar_t * jarg4) 
{
//do some stuff with strings
}

if you use SWIG, swig will try to autogenerate the above code, but it is a harsh master.

如果你使用SWIG,swig将尝试自动生成上面的代码,但它是一个苛刻的主人。

i used managed c++ once, but i don't remember quite what i thought of it.

我曾经使用过托管c ++,但我不记得我对它的看法。

#4


I think it depends on how much of the library functionality you actually need to expose.

我认为这取决于您实际需要暴露多少库功能。

I don't know about creating a managed C++ wrapper, but I've personally used two other approaches to solving this problem:

我不知道创建托管C ++包装器,但我个人使用了另外两种方法来解决这个问题:

  1. Use SWIG to automatically generate C# PInvoke wrappers for your C++ classes. This sort of works but is really only worth it if you need to expose a lot of classes and members. In my experience, the auto-generated code still needed some tweaking by hand.

    使用SWIG为您的C ++类自动生成C#PInvoke包装器。这种工作,但是如果你需要暴露很多类和成员,那真的是值得的。根据我的经验,自动生成的代码仍然需要手动调整。

  2. Write unmanaged C wrappers for just the functionality you need, export them from a DLL, and hand-code the few PInvoke wrappers you need to import into C#. I've found this is more appropriate in some cases, e.g. there's a large C++ class library that performs different types of image file conversions, but all you really want to expose is a single function DoTheConversion(LPWSTR inputFile). My C# program didn't need to know all the intricacies of the underlying class library.

    编写非托管C包装器以获得所需的功能,从DLL导出它们,并手动编写需要导入C#的几个PInvoke包装器。我发现这在某些情况下更合适,例如:有一个大型的C ++类库可以执行不同类型的图像文件转换,但您真正想要公开的只是一个函数DoTheConversion(LPWSTR inputFile)。我的C#程序不需要知道底层类库的所有复杂性。

#5


Reading some of these articles might be a start - it's a rather broad subject, and there is no 'perfect' way to do it:

阅读其中一些文章可能是一个开始 - 这是一个相当广泛的主题,并没有“完美”的方式来做到这一点:

http://www.ondotnet.com/pub/a/dotnet/2004/03/29/mcpp_part3.html http://www.codeguru.com/cpp/cpp/cpp_managed/interop/article.php/c6867

None of these approaches uses p/invoke, and it's an approach we use in the projects I work at where we need to interface an insanely old c++-service library.

这些方法都没有使用p / invoke,这是我们在我需要连接一个疯狂的旧c ++服务库的项目中使用的方法。

#1


You might consider writing a COM wrapper for your C++ code using ATL. I show how to do this in a blog post. This is how Microsoft exposes functionality that they wrote in C++ (e.g. Windows 7 Libraries features). COM is easily consumed by .NET/C# (see this post). If you go this route, you might consider registration free COM if you don't need to share your wrapper with others.

您可以考虑使用ATL为C ++代码编写COM包装器。我在博客文章中展示了如何做到这一点。这就是Microsoft如何公开他们用C ++编写的功能(例如Windows 7库功能)。 COM很容易被.NET / C#使用(参见这篇文章)。如果你走这条路线,如果你不需要与他人分享你的包装,你可以考虑免注册COM。

#2


You can write managed and unmanaged C++ in the same project. So you can write a wrapper in Managed C++ that calls your native c++ classes etc. Then in C# your managed C++ classes will appear just like any other .net reference. No need to use P/Invoke in this case.

您可以在同一个项目中编写托管和非托管C ++。因此,您可以在Managed C ++中编写一个包装器来调用您的本机c ++类等。然后在C#中,您的托管C ++类将像任何其他.net引用一样出现。在这种情况下无需使用P / Invoke。

#3


you have two options, one is called ijw "it just works" where you can write managed c++ and call unmanaged c++. The other option requires the use of pinvoke.

你有两个选择,一个名为ijw“它只是工作”你可以编写托管c ++并调用非托管c ++。另一种选择需要使用pinvoke。

if you use pinvoke you'll have something like this

如果你使用pinvoke,你会有类似的东西

C#

somefunction("str1", "str2", "str3", "str4"); 

[DllImport(@"myproj.dll", EntryPoint = "somefunction")]
public static extern IntPtr SomeFunction([MarshalAs(UnmanagedType.LPWStr)]string jarg1, [MarshalAs(UnmanagedType.LPWStr)]string jarg2, [MarshalAs(UnmanagedType.LPWStr)]string jarg3, [MarshalAs(UnmanagedType.LPWStr)]string jarg4);

c++

extern "C" __declspec(dllexport) void* __stdcall somefunction(wchar_t * jarg1, wchar_t * jarg2, wchar_t * jarg3, wchar_t * jarg4) 
{
//do some stuff with strings
}

if you use SWIG, swig will try to autogenerate the above code, but it is a harsh master.

如果你使用SWIG,swig将尝试自动生成上面的代码,但它是一个苛刻的主人。

i used managed c++ once, but i don't remember quite what i thought of it.

我曾经使用过托管c ++,但我不记得我对它的看法。

#4


I think it depends on how much of the library functionality you actually need to expose.

我认为这取决于您实际需要暴露多少库功能。

I don't know about creating a managed C++ wrapper, but I've personally used two other approaches to solving this problem:

我不知道创建托管C ++包装器,但我个人使用了另外两种方法来解决这个问题:

  1. Use SWIG to automatically generate C# PInvoke wrappers for your C++ classes. This sort of works but is really only worth it if you need to expose a lot of classes and members. In my experience, the auto-generated code still needed some tweaking by hand.

    使用SWIG为您的C ++类自动生成C#PInvoke包装器。这种工作,但是如果你需要暴露很多类和成员,那真的是值得的。根据我的经验,自动生成的代码仍然需要手动调整。

  2. Write unmanaged C wrappers for just the functionality you need, export them from a DLL, and hand-code the few PInvoke wrappers you need to import into C#. I've found this is more appropriate in some cases, e.g. there's a large C++ class library that performs different types of image file conversions, but all you really want to expose is a single function DoTheConversion(LPWSTR inputFile). My C# program didn't need to know all the intricacies of the underlying class library.

    编写非托管C包装器以获得所需的功能,从DLL导出它们,并手动编写需要导入C#的几个PInvoke包装器。我发现这在某些情况下更合适,例如:有一个大型的C ++类库可以执行不同类型的图像文件转换,但您真正想要公开的只是一个函数DoTheConversion(LPWSTR inputFile)。我的C#程序不需要知道底层类库的所有复杂性。

#5


Reading some of these articles might be a start - it's a rather broad subject, and there is no 'perfect' way to do it:

阅读其中一些文章可能是一个开始 - 这是一个相当广泛的主题,并没有“完美”的方式来做到这一点:

http://www.ondotnet.com/pub/a/dotnet/2004/03/29/mcpp_part3.html http://www.codeguru.com/cpp/cpp/cpp_managed/interop/article.php/c6867

None of these approaches uses p/invoke, and it's an approach we use in the projects I work at where we need to interface an insanely old c++-service library.

这些方法都没有使用p / invoke,这是我们在我需要连接一个疯狂的旧c ++服务库的项目中使用的方法。