如何从本机 C++ 调用 C# 库(使用 C++CLI 和 IJW) [英] How to call a C# library from Native C++ (using C++CLI and IJW)

查看:45
本文介绍了如何从本机 C++ 调用 C# 库(使用 C++CLI 和 IJW)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

背景: 作为更大任务的一部分,我需要使非托管 C++ 和 C 代码可以访问 C# 库.为了自己回答这个问题,过去几天/几周我一直在学习 C++/CLI.

Background: As part of a larger assignment I need to make a C# library accessible to unmanaged C++ and C code. In an attempt to answer this question myself I have been learning C++/CLI the past few days/ weeks.

似乎有许多不同的方法可以使用来自非托管 C++ 和 C 的 C# dll.一些简短的答案似乎是:使用 Interlope 服务,使用 .com.和 regasm,使用 PInvoke(似乎只是从 C# 到 C++),并在 C++/CLR(似乎是 Interlope 服务)中使用 IJW.我认为最好设置一个库,它可能是一个 CLR 包装器,它使用 IJW 代表本机 C++ 和 C 代码调用我的 C# dll.

There seems to be a number of different ways to achieve using a C# dll from unmanaged C++ and C. Some of the answers in brief appear to be: using Interlope services, Using .com. and regasm, Using PInvoke (which appears to go from C# to C++ only), and using IJW in the C++/CLR (which appears to be Interlope services). I am thinking it would be best to set up a library that is perhaps a CLR wrapper that uses IJW to call my C# dll on the behalf of native C++ and C code.

具体说明:我需要将字符串和 int 的值从 C++ 代码传递给 C# dll,并返回 void.

Specifics: I need to pass values of string as well as int to a C# dll from c++ code, and return void.

相关性:许多公司有很多借口混合搭配 C++、C 和 C#.性能:非托管代码通常更快,接口:托管接口通常更容易维护、部署,并且通常更容易看,经理也告诉我们.遗留代码也迫使我们这样做.它就在那里(就像我们爬过的山一样).虽然如何从 C# 调用 C++ 库的示例很多.通过谷歌搜索很难找到如何从 C++ 代码调用 C# 库的示例,尤其是如果您想查看更新的 4.0+ 代码.

Relevance: Many companies have many excuses to mix and match C++, C and C#. Performance: unmanaged code is usually faster, interfaces: Managed interfaces are generally easier to maintain, deploy, and are often easier on the eyes, Managers tell us too. Legacy code forces us too. It was there (Like the mountain that we climbed). While examples of how to call a C++ library from C# are abundant. Examples of how to call C# libraries from C++ code are difficult to find via Googling especially if you want to see updated 4.0+ code.

软件:C#、C++/CLR、C++、C、Visual Studio 2010 和 .NET 4.0

Software: C#, C++/CLR, C++, C, Visual Studio 2010, and .NET 4.0

问题详情:好的多部分问题:

  1. 使用 com 对象有优势吗?还是 PInvoke?或者其他什么方法?(我觉得这里的学习曲线同样陡峭,即使我确实在 Google Land 中找到了有关该主题的更多信息.IJW 似乎承诺了我想要它做的事情.我应该放弃寻找 IJW 解决方案吗?而是专注于此?)(优势/劣势?)

  1. Is there an advantage to using com objects? Or the PInvoke? Or some other method? (I feel like the learning curve here will be just as steep, even though I do find more information on the topic in Google Land. IJW seems to promise what I want it to do. Should I give up on looking for an IJW solution and focus on this instead?) (Advantage/ disadvantage?)

我是否正确地认为有一个解决方案可以让我编写一个在 C++/CLR 中使用 IJW 的包装器?我在哪里可以找到关于这个主题的更多信息,不要说我没有足够的谷歌/或者在没有告诉我你在哪里看到它的情况下查看 MSDN.(我想我更喜欢这个选项,努力编写清晰简单的代码.)

Am I correct in imagining that there is a solution where I write a wrapper that that utilizes IJW in the C++/CLR? Where can I find more information on this topic, and don’t say I didn’t Google enough/ or look at MSDN without telling me where you saw it there. (I think I prefer this option, in the effort to write clear and simple code.)

缩小问题范围:我觉得我真正的问题和需要是回答以下较小的问题:如何设置非托管 C++ 文件可以在 Visual Studio 中使用的 C++/CLR 库.我认为,如果我可以简单地在非托管 C++ 代码中实例化一个托管 C++ 类,那么我也许可以解决其余的问题(接口和包装等).我希望我的主要愚蠢之处在于尝试在 Visual Studio 中设置引用/#includes 等,但显然我可能会有其他误解.也许这整个事情的答案可能只是一个教程或说明的链接,可以帮助我解决这个问题.

A narrowing of question scope: I feel that my true issue and need is answering the smaller question that follows: How do I set up a C++/CLR library that an unmanaged C++ file can use within visual studio. I think that if I could simply instantiate a managed C++ class in unmanaged C++ code, then I might be able work out the rest (interfacing and wrapping etc.). I expect that my main folly is in trying to set up references/#includes etc. within Visual Studio, thought clearly I could have other misconceptions. Perhaps the answer to this whole thing could be just a link to a tutorial or instructions that help me with this.

研究:我一遍又一遍地使用 Google 搜索和 Bing,并取得了一些成功.我找到了许多向您展示如何使用 C# 代码中的非托管库的链接.我承认已经有一些链接展示了如何使用 com 对象来做到这一点.针对 VS 2010 的结果并不多.

Research: I have Googled and Binged over and over with some success. I have found many links that show you how to use an unmanaged library from C# code. And I will admit that there have been some links that show how to do it using com objects. Not many results were targeted at VS 2010.

参考资料:我一遍又一遍地阅读了很多帖子.我试图解决最相关的问题.有些似乎非常接近答案,但我似乎无法让它们发挥作用.我怀疑我缺少的东西非常小,例如滥用关键字 ref,或缺少 #include 或 using 语句,或滥用名称空间,或实际上未正确使用 IJW 功能,或缺少 VS 的设置需要正确处理编译等.所以你想知道,为什么不包括代码?好吧,我觉得我不是在一个我理解并期望我必须工作的代码的地方.我想待在一个我能理解的地方,当我到达那里时,也许我需要帮助修复它.我将随机包含其中的两个链接,但在我当前的 Hitpoint 级别,我不允许将它们全部显示.

References: I have read over and over many posts. I have tried to work through the most relevant ones. Some seem tantalizingly close to the answer, but I just can’t seem to get them to work. I suspect that the thing that I am missing is tantalizingly small, such as misusing the keyword ref, or missing a #include or using statement, or a misuse of namespace, or not actually using the IJW feature properly, or missing a setting that VS needs to handle the compilation correctly, etc. So you wonder, why not include the code? Well I feel like I am not at a place where I understand and expect the code I have to work. I want to be in a place where I understand it, when I get there maybe then I'll need help fixing it. I'll randomly include two of the links but I am not permitted to show them all at my current Hitpoint level.

http://www.codeproject.com/Articles/35437/在托管代码和非托管代码之间移动数据

这在从 C++ 到 Visual Basic 和通过 C++CLR 返回的两个方向上从托管和非托管代码调用代码,当然我对 C# 感兴趣.:http://www.codeproject.com/Articles/9903/Calling-Managed-Code-from-Unmanaged-Code-和-副

This calls code from managed and unmanaged code in both directions going from C++ to Visual Basic and back via C++CLR, and of course I am interested in C#.: http://www.codeproject.com/Articles/9903/Calling-Managed-Code-from-Unmanaged-Code-and-vice

推荐答案

我发现一些东西至少开始回答我自己的问题.以下两个链接包含来自 Microsoft 的 wmv 文件,这些文件演示了在非托管 C++ 中使用 C# 类.

I found something that at least begins to answer my own question. The following two links have wmv files from Microsoft that demonstrate using a C# class in unmanaged C++.

第一个使用 COM 对象和 regasm:http://msdn.microsoft.com/en-us/vstudio/bb892741.

This first one uses a COM object and regasm: http://msdn.microsoft.com/en-us/vstudio/bb892741.

第二个使用 C++/CLI 的特性来包装 C# 类:http://msdn.microsoft.com/en-us/vstudio/bb892742.我已经能够从托管代码实例化一个 c# 类并检索视频中的字符串.它非常有帮助,但它只回答了我问题的 2/3,因为我想将一个带有字符串周长的类实例化为一个 c# 类.作为概念证明,我更改了示例中为以下方法提供的代码,并实现了这一目标.当然,我还添加了一个修改过的 {public string PickDate(string Name)} 方法来对名称字符串做一些事情来向自己证明它有效.

This second one uses the features of C++/CLI to wrap the C# class: http://msdn.microsoft.com/en-us/vstudio/bb892742. I have been able to instantiate a c# class from managed code and retrieve a string as in the video. It has been very helpful but it only answers 2/3rds of my question as I want to instantiate a class with a string perimeter into a c# class. As a proof of concept I altered the code presented in the example for the following method, and achieved this goal. Of course I also added a altered the {public string PickDate(string Name)} method to do something with the name string to prove to myself that it worked.

wchar_t * DatePickerClient::pick(std::wstring nme)
{
    IntPtr temp(ref);// system int pointer from a native int
    String ^date;// tracking handle to a string (managed)
    String ^name;// tracking handle to a string (managed)
    name = gcnew String(nme.c_str());
    wchar_t *ret;// pointer to a c++ string
    GCHandle gch;// garbage collector handle
    DatePicker::DatePicker ^obj;// reference the c# object with tracking handle(^)
    gch = static_cast<GCHandle>(temp);// converted from the int pointer 
    obj = static_cast<DatePicker::DatePicker ^>(gch.Target);
    date = obj->PickDate(name);
    ret = new wchar_t[date->Length +1];
    interior_ptr<const wchar_t> p1 = PtrToStringChars(date);// clr pointer that acts like pointer
    pin_ptr<const wchar_t> p2 = p1;// pin the pointer to a location as clr pointers move around in memory but c++ does not know about that.
    wcscpy_s(ret, date->Length +1, p2);
    return ret;
}

我的部分问题是:什么更好?从我在许多研究中读到的答案是,COM 对象被认为更易于使用,而使用包装器可以实现更好的控制.在某些情况下,使用包装器可以(但并非总是)减小 thunk 的大小,因为 COM 对象自动具有标准大小的占用空间,而包装器只需要它们的大小即可.

Part of my question was: What is better? From what I have read in many many efforts to research the answer is that COM objects are considered easier to use, and using a wrapper instead allows for greater control. In some cases using a wrapper can (but not always) reduce the size of the thunk, as COM objects automatically have a standard size footprint and wrappers are only as big as they need to be.

thunk(正如我上面使用的)是指在 COM 对象的情况下 C# 和 C++ 之间使用的空间时间和资源,在编码的情况下在 C++/CLI 和本机 C++ 之间使用的空间时间和资源 - 使用C++/CLI 包装器.所以我的答案的另一部分应该包括一个警告,即越过 thunk 边界超过绝对必要的做法是不好的做法,不建议访问循环内的 thunk 边界,并且可能会错误地设置包装器,以便它加倍 thunk(跨越边界两次,只需要一个 thunk)没有代码对像我这样的新手来说似乎是不正确的.

The thunk (as I have used above) refers to the space time and resources used in between C# and C++ in the case of the COM object, and in between C++/CLI and native C++ in the case of coding-using a C++/CLI Wrapper. So another part of my answer should include a warning that crossing the thunk boundary more than absolutely necessary is bad practice, accessing the thunk boundary inside a loop is not recommended, and that it is possible to set up a wrapper incorrectly so that it double thunks (crosses the boundary twice where only one thunk is called for) without the code seeming to be incorrect to a novice like me.

关于 wmv 的两个注释.第一:一些镜头在两者中重复使用,不要被愚弄.起初它们看起来相同,但它们确实涵盖了不同的主题.其次,有一些额外的功能,例如编组,现在是 CLI 的一部分,但没有包含在 wmv 中.

Two notes about the wmv's. First: some footage is reused in both, don't be fooled. At first they seem the same but they do cover different topics. Second, there are some bonus features such as marshalling that are now a part of the CLI that are not covered in the wmv's.

请注意,您的安装会产生一个后果,CLR 将找不到您的 C++ 包装器.您必须确认 c++ 应用程序安装在使用它的任何/每个目录中,或者在安装时将库(然后需要强命名)添加到 GAC.这也意味着在开发环境中的任何一种情况下,您可能都必须将库复制到应用程序调用它的每个目录.

Note there is a consequence for your installs, your c++ wrapper will not be found by the CLR. You will have to either confirm that the c++ application installs in any/every directory that uses it, or add the library (which will then need to be strongly named) to the GAC at install time. This also means that with either case in development environments you will likely have to copy the library to each directory where applications call it.

这篇关于如何从本机 C++ 调用 C# 库(使用 C++CLI 和 IJW)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆