如何从本地c++调用c#库(使用c++ \CLI和IJW)

时间:2021-11-23 04:19:40

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代码具有可访问性。为了回答这个问题,我过去几天或几周一直在学习c++ /CLI。

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.

使用unmanaged c++和C.的c# dll来实现的方法似乎有很多,其中一些简单的答案似乎是:使用Interlope服务,使用。com。并且使用PInvoke(似乎是从c#到c++只),并在c++ /CLR中使用IJW(看起来是Interlope服务)。我认为最好建立一个可能是CLR包装器的库,它使用IJW代表本机c++和C代码调用我的c# dll。

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

细节:我需要从c++代码中将字符串值和int值传递给c# dll,并返回void。

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和c#。性能:非托管代码通常速度更快,接口:管理接口通常更容易维护、部署,管理人员还告诉我们,这些接口通常也更容易实现。遗留代码也迫使我们这样做。它就在那里(就像我们爬的那座山)。虽然如何从c#调用c++库的示例很多。如果你想看到更新的4.0+代码,你很难通过google搜索来找到如何调用c++代码中的c#库。

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

软件:c#、c++ /CLR、c++、C、Visual Studio 2010、。net 4.0

Question details: OK multi-part question:

问题细节:好的多部分问题:

  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?)

    使用com对象有什么好处吗?段或PInvoke吗?还是其他方法?(我觉得这里的学习曲线也一样陡峭,尽管我确实在谷歌平台上找到了更多关于这个主题的信息。IJW似乎承诺了我想要它做的事情。我是否应该放弃寻找一种IJW解决方案而专注于此?

  2. 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++ /CLR中使用IJW ?我在哪里可以找到更多关于这个话题的信息,不要说我没有谷歌做得足够好/或者不告诉我你在哪里见过MSDN。(我想我更喜欢这个选项,因为我想写清楚简单的代码。)

  3. 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.

    缩小问题范围:我觉得我真正的问题和需要是回答下面这个小问题:我如何设置一个c++ /CLR库,一个非托管的c++文件可以在visual studio中使用它。我认为,如果我可以简单地在非托管c++代码中实例化一个托管c++类,那么我就可以解决其余的问题(接口和包装等)。我认为我的主要愚蠢之处在于试图在Visual Studio中建立引用/#include等,我认为我可能有其他的误解。也许这整件事的答案可能只是一个链接到教程或指导帮助我做这个。

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.

研究:我在谷歌上搜索了一下,并成功地翻看了一遍又一遍。我找到了许多链接,它们向您展示如何使用c#代码中的非托管库。我承认有一些链接展示了如何使用com对象来实现它。针对VS 2010的结果并不多。

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.

参考文献:我读过很多文章。我已经试着通过最相关的工作。有些人似乎很接近答案,但我似乎无法让他们工作。我怀疑我思念是非常小的东西,比如滥用关键字ref,或失踪# include或使用声明,或滥用名称空间,或者没有正确使用IJW特性,或失踪和需要处理的设置正确编译,等等。所以你想知道,为什么不包括代码吗?好吧,我觉得我不是在一个我能理解和期待我必须工作的代码的地方。我想去一个我能理解的地方,当我到达那里的时候,我可能需要帮助来修复它。我将随机包含两个链接,但不允许在当前的生命值级别显示它们。

http://www.codeproject.com/Articles/35437/Moving-Data-between-Managed-Code-and-Unmanaged-Cod

http://www.codeproject.com/Articles/35437/Moving-Data-between-Managed-Code-and-Unmanaged-Cod

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

它从托管和非托管代码调用代码,从c++到Visual Basic,再从c++ CLR返回,当然我对c#感兴趣。:http://www.codeproject.com/Articles/9903/Calling-Managed-Code-from-Unmanaged-Code-and-vice

5 个解决方案

#1


28  

You can do this fairly easily.

这很容易做到。

  1. Create an .h/.cpp combo
  2. 创建一个. h /。cpp组合
  3. Enable /clr on the newly create .cpp file. (CPP -> Right click -> Properties)
  4. 在新创建的.cpp文件上启用/clr。(CPP ->右击->属性)
  5. Set the search path for "additional #using directories" to point towards your C# dll.
  6. 设置“附加#使用目录”的搜索路径,指向c# dll。

Native.h

Native.h

void NativeWrapMethod();

Native.cpp

Native.cpp

#using <mscorlib.dll>
#using <MyNet.dll>

using namespace MyNetNameSpace;

void NativeWrapMethod()
{
    MyNetNameSpace::MyManagedClass::Method(); // static method
}

That's the basics of using a C# lib from C++\CLI with native code. (Just reference Native.h where needed, and call the function.)

这就是使用来自c++ \CLI的c# lib与本机代码的基础。(仅参考本机。h在需要的地方,调用函数)

Using C# code with managed C++\CLI code is roughly the same.

使用带有托管c++ \CLI代码的c#代码大致相同。

There is a lot of misinformation on this subject, so, hopefully this saves someone a lot of hassle. :)

在这个问题上有很多错误的信息,所以,希望这能给某人省去很多麻烦。:)


I've done this in: VS2010 - VS2012 (It probably works in VS2008 too.)

我在:VS2010 - VS2012(它可能也适用于VS2008)中做过这件事。

#2


13  

If you want to use COM, here's my solution for this problem:

如果你想用COM,我的解决方法是:

C# library

c#库

First of all you need a COM compatible library.

首先,您需要一个COM兼容的库。

  • You already got one? Perfect, you can skip this part.

    你已经有一个了吗?很好,你可以跳过这部分。

  • You have access to the library? Make sure it's COM compatible by following the steps.

    你可以进入图书馆吗?按照步骤来确保它是可兼容的。

    1. Make sure that you checked the "Register for COM interop" option in the properties of your project. Properties -> Build -> Scroll down -> Register for COM interop
    2. 确保您在项目的属性中检查了“Register for COM interop”选项。属性->构建->向下滚动->寄存器为COM对讲

The following screenshots shows where you find this option.

下面的屏幕截图显示了在哪里可以找到这个选项。

如何从本地c++调用c#库(使用c++ \CLI和IJW)

  1. All the interfaces and classes that should be available need to have a GUID

    所有应该可用的接口和类都需要有一个GUID。

    namespace NamespaceOfYourProject
    {
        [Guid("add a GUID here")]
        public interface IInterface
        {
            void Connect();
    
            void Disconnect();
        }
    }
    
    namespace NamespaceOfYourProject
    {
         [Guid("add a GUID here")]
         public class ClassYouWantToUse: IInterface
         {
             private bool connected;
    
             public void Connect()
             {
                 //add code here
             }
    
             public void Disconnect()
             {
                 //add code here
             }
         }
    }
    

So that's pretty much what you have to do with your C# code. Let's continue with the C++ code.

这就是你对c#代码所做的。让我们继续使用c++代码。

C++

c++

  1. First of all we need to import the C# library.
  2. 首先,我们需要导入c#库。

After compiling your C# library there should be a .tlb file.

编译c#库之后,应该有一个.tlb文件。

#import "path\to\the\file.tlb"

If you import this new created file to your file.cpp you can use your object as a local variable.

如果您将这个新创建的文件导入到您的文件中。您可以将对象用作本地变量。

#import "path\to\the\file.tlb"

int _tmain(int argc, _TCHAR* argv[])
{
    CoInitialize(NULL);

    NamespaceOfYourProject::IInterfacePtr yourClass(__uuidof(NamespaceOfYourProject::ClassYouWantToUse));

    yourClass->Connect();

    CoUninitialize();
}
  1. Using your class as an attribute.
  2. 使用类作为属性。

You will noticed that the first step only works with a local variable. The following code shows how to use it as a attribute. Related to this question.

您将注意到,第一步只对局部变量起作用。下面的代码展示了如何将它用作属性。与这个问题有关。

You will need the CComPtr, which is located in atlcomcli.h. Include this file in your header file.

你需要CComPtr,它位于atlcomcli.h。在你的头文件中包含这个文件。

CPlusPlusClass.h

CPlusPlusClass.h

#include <atlcomcli.h> 
#import "path\to\the\file.tlb"

class CPlusPlusClass
{
public:
    CPlusPlusClass(void);
    ~CPlusPlusClass(void);
    void Connect(void);

private:
    CComPtr<NamespaceOfYourProject::IInterface> yourClass;
}

CPlusPlusClass.cpp

CPlusPlusClass.cpp

CPlusPlusClass::CPlusPlusClass(void)
{
    CoInitialize(NULL);

    yourClass.CoCreateInstance(__uuidof(NamespaceOfYourProject::ClassYouWantToUse));

}

CPlusPlusClass::~CPlusPlusClass(void)
{
    CoUninitialize();
}

void CPlusPlusClass::Connect(void)
{
    yourClass->Connect();
}

That's it! Have fun with your C# classes in C++ with COM.

就是这样!在c++中与COM一起享受c#类的乐趣。

#3


7  

The absolute best way I have found to do this is create a c++/cli bridge that connects the c# code to your native C++. I would not recommend using COM objects to solve your problem. You can do this with 3 different projects.

我发现最好的方法是创建一个c++/cli bridge,将c#代码连接到本地c++。我不建议使用COM对象来解决您的问题。你可以用3个不同的项目来完成。

  • First Project: C# library
  • 第一个项目:c#库
  • Second Project: C++/CLI bridge (this wraps the C# library)
  • 第二个项目:c++ /CLI bridge(这个包括了c#库)
  • Third Project: Native C++ application that uses the second project
  • 第三个项目:使用第二个项目的本机c++应用程序

A good visual/tutorial on this can be found here, and the best complete walkthrough that I have found to do this can be found here! Between those two links and a little grit you should be able to hammer out creating a C++/CLI bridge that allows you to use C# code in your native C++.

在这里可以找到一个很好的视觉/教程,在这里可以找到我找到的最好的完整的演练!在这两个链接和一些细节之间,您应该能够创建一个c++ /CLI bridge,允许您在本地c++中使用c#代码。

#4


4  

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++.

我发现了一些至少可以回答我自己问题的东西。以下两个链接有来自微软的wmv文件,演示了如何在非托管c++中使用c#类。

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

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

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.

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

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;
}

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.

我的部分问题是:什么是更好的?从我读到的许多研究结果来看,COM对象被认为更容易使用,而使用包装器可以获得更大的控制。在某些情况下,使用包装器可以(但不总是)减少thunk的大小,因为COM对象自动具有标准的大小,而包装器也只有它们需要的那么大。

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.

thunk(如上所述)是指在COM对象的情况下,c#和c++之间使用的空间时间和资源,以及在使用c++ /CLI包装的情况下,在C++/CLI和本机c++之间使用的时间和资源。所以我的答案应该包括一个警告的另一部分,穿越铛边界绝对必要的多是不好的实践中,访问铛边界内循环不推荐,而且它可以建立一个包装错误,双铛(跨越边界的两倍,只要求一个铛)没有代码似乎是不正确的,像我这样的新手。

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.

关于wmv的两个音符。首先:有些镜头在两者中都被重复使用,不要被愚弄。一开始他们看起来是一样的,但是他们确实涉及不同的话题。其次,还有一些额外的特性,比如编组,它们现在是CLI的一部分,wmv中没有涉及到这些特性。

Edit:

编辑:

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++包装器将不会被CLR发现。您必须确认c++应用程序安装在使用它的任何/每个目录中,或者在安装时向GAC添加库(然后需要对库进行强命名)。这也意味着在开发环境中,无论哪种情况,都可能需要将库复制到应用程序调用它的每个目录。

#5


0  

I did a bunch of looking around and found a relatively recent article by Microsoft detailing how it can be done (there is a lot of old infomration floating around). From the article itself:

我四处查看了一下,发现了微软最近的一篇文章,详细介绍了它是如何实现的(到处都是旧的信息)。从文章本身:

The code sample uses the CLR 4 hosting APIs to host CLR in a native C++ project, load and invoke .NET assemblies

代码示例使用CLR 4托管api在本地c++项目中托管CLR,加载和调用。net程序集。

https://code.msdn.microsoft.com/CppHostCLR-e6581ee0

https://code.msdn.microsoft.com/CppHostCLR-e6581ee0

Basically it describes it in two steps:

基本上它分两个步骤来描述它:

  1. Load the CLR into a process
  2. 将CLR加载到一个进程中。
  3. Load your assembly.
  4. 加载程序集。

#1


28  

You can do this fairly easily.

这很容易做到。

  1. Create an .h/.cpp combo
  2. 创建一个. h /。cpp组合
  3. Enable /clr on the newly create .cpp file. (CPP -> Right click -> Properties)
  4. 在新创建的.cpp文件上启用/clr。(CPP ->右击->属性)
  5. Set the search path for "additional #using directories" to point towards your C# dll.
  6. 设置“附加#使用目录”的搜索路径,指向c# dll。

Native.h

Native.h

void NativeWrapMethod();

Native.cpp

Native.cpp

#using <mscorlib.dll>
#using <MyNet.dll>

using namespace MyNetNameSpace;

void NativeWrapMethod()
{
    MyNetNameSpace::MyManagedClass::Method(); // static method
}

That's the basics of using a C# lib from C++\CLI with native code. (Just reference Native.h where needed, and call the function.)

这就是使用来自c++ \CLI的c# lib与本机代码的基础。(仅参考本机。h在需要的地方,调用函数)

Using C# code with managed C++\CLI code is roughly the same.

使用带有托管c++ \CLI代码的c#代码大致相同。

There is a lot of misinformation on this subject, so, hopefully this saves someone a lot of hassle. :)

在这个问题上有很多错误的信息,所以,希望这能给某人省去很多麻烦。:)


I've done this in: VS2010 - VS2012 (It probably works in VS2008 too.)

我在:VS2010 - VS2012(它可能也适用于VS2008)中做过这件事。

#2


13  

If you want to use COM, here's my solution for this problem:

如果你想用COM,我的解决方法是:

C# library

c#库

First of all you need a COM compatible library.

首先,您需要一个COM兼容的库。

  • You already got one? Perfect, you can skip this part.

    你已经有一个了吗?很好,你可以跳过这部分。

  • You have access to the library? Make sure it's COM compatible by following the steps.

    你可以进入图书馆吗?按照步骤来确保它是可兼容的。

    1. Make sure that you checked the "Register for COM interop" option in the properties of your project. Properties -> Build -> Scroll down -> Register for COM interop
    2. 确保您在项目的属性中检查了“Register for COM interop”选项。属性->构建->向下滚动->寄存器为COM对讲

The following screenshots shows where you find this option.

下面的屏幕截图显示了在哪里可以找到这个选项。

如何从本地c++调用c#库(使用c++ \CLI和IJW)

  1. All the interfaces and classes that should be available need to have a GUID

    所有应该可用的接口和类都需要有一个GUID。

    namespace NamespaceOfYourProject
    {
        [Guid("add a GUID here")]
        public interface IInterface
        {
            void Connect();
    
            void Disconnect();
        }
    }
    
    namespace NamespaceOfYourProject
    {
         [Guid("add a GUID here")]
         public class ClassYouWantToUse: IInterface
         {
             private bool connected;
    
             public void Connect()
             {
                 //add code here
             }
    
             public void Disconnect()
             {
                 //add code here
             }
         }
    }
    

So that's pretty much what you have to do with your C# code. Let's continue with the C++ code.

这就是你对c#代码所做的。让我们继续使用c++代码。

C++

c++

  1. First of all we need to import the C# library.
  2. 首先,我们需要导入c#库。

After compiling your C# library there should be a .tlb file.

编译c#库之后,应该有一个.tlb文件。

#import "path\to\the\file.tlb"

If you import this new created file to your file.cpp you can use your object as a local variable.

如果您将这个新创建的文件导入到您的文件中。您可以将对象用作本地变量。

#import "path\to\the\file.tlb"

int _tmain(int argc, _TCHAR* argv[])
{
    CoInitialize(NULL);

    NamespaceOfYourProject::IInterfacePtr yourClass(__uuidof(NamespaceOfYourProject::ClassYouWantToUse));

    yourClass->Connect();

    CoUninitialize();
}
  1. Using your class as an attribute.
  2. 使用类作为属性。

You will noticed that the first step only works with a local variable. The following code shows how to use it as a attribute. Related to this question.

您将注意到,第一步只对局部变量起作用。下面的代码展示了如何将它用作属性。与这个问题有关。

You will need the CComPtr, which is located in atlcomcli.h. Include this file in your header file.

你需要CComPtr,它位于atlcomcli.h。在你的头文件中包含这个文件。

CPlusPlusClass.h

CPlusPlusClass.h

#include <atlcomcli.h> 
#import "path\to\the\file.tlb"

class CPlusPlusClass
{
public:
    CPlusPlusClass(void);
    ~CPlusPlusClass(void);
    void Connect(void);

private:
    CComPtr<NamespaceOfYourProject::IInterface> yourClass;
}

CPlusPlusClass.cpp

CPlusPlusClass.cpp

CPlusPlusClass::CPlusPlusClass(void)
{
    CoInitialize(NULL);

    yourClass.CoCreateInstance(__uuidof(NamespaceOfYourProject::ClassYouWantToUse));

}

CPlusPlusClass::~CPlusPlusClass(void)
{
    CoUninitialize();
}

void CPlusPlusClass::Connect(void)
{
    yourClass->Connect();
}

That's it! Have fun with your C# classes in C++ with COM.

就是这样!在c++中与COM一起享受c#类的乐趣。

#3


7  

The absolute best way I have found to do this is create a c++/cli bridge that connects the c# code to your native C++. I would not recommend using COM objects to solve your problem. You can do this with 3 different projects.

我发现最好的方法是创建一个c++/cli bridge,将c#代码连接到本地c++。我不建议使用COM对象来解决您的问题。你可以用3个不同的项目来完成。

  • First Project: C# library
  • 第一个项目:c#库
  • Second Project: C++/CLI bridge (this wraps the C# library)
  • 第二个项目:c++ /CLI bridge(这个包括了c#库)
  • Third Project: Native C++ application that uses the second project
  • 第三个项目:使用第二个项目的本机c++应用程序

A good visual/tutorial on this can be found here, and the best complete walkthrough that I have found to do this can be found here! Between those two links and a little grit you should be able to hammer out creating a C++/CLI bridge that allows you to use C# code in your native C++.

在这里可以找到一个很好的视觉/教程,在这里可以找到我找到的最好的完整的演练!在这两个链接和一些细节之间,您应该能够创建一个c++ /CLI bridge,允许您在本地c++中使用c#代码。

#4


4  

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++.

我发现了一些至少可以回答我自己问题的东西。以下两个链接有来自微软的wmv文件,演示了如何在非托管c++中使用c#类。

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

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

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.

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

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;
}

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.

我的部分问题是:什么是更好的?从我读到的许多研究结果来看,COM对象被认为更容易使用,而使用包装器可以获得更大的控制。在某些情况下,使用包装器可以(但不总是)减少thunk的大小,因为COM对象自动具有标准的大小,而包装器也只有它们需要的那么大。

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.

thunk(如上所述)是指在COM对象的情况下,c#和c++之间使用的空间时间和资源,以及在使用c++ /CLI包装的情况下,在C++/CLI和本机c++之间使用的时间和资源。所以我的答案应该包括一个警告的另一部分,穿越铛边界绝对必要的多是不好的实践中,访问铛边界内循环不推荐,而且它可以建立一个包装错误,双铛(跨越边界的两倍,只要求一个铛)没有代码似乎是不正确的,像我这样的新手。

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.

关于wmv的两个音符。首先:有些镜头在两者中都被重复使用,不要被愚弄。一开始他们看起来是一样的,但是他们确实涉及不同的话题。其次,还有一些额外的特性,比如编组,它们现在是CLI的一部分,wmv中没有涉及到这些特性。

Edit:

编辑:

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++包装器将不会被CLR发现。您必须确认c++应用程序安装在使用它的任何/每个目录中,或者在安装时向GAC添加库(然后需要对库进行强命名)。这也意味着在开发环境中,无论哪种情况,都可能需要将库复制到应用程序调用它的每个目录。

#5


0  

I did a bunch of looking around and found a relatively recent article by Microsoft detailing how it can be done (there is a lot of old infomration floating around). From the article itself:

我四处查看了一下,发现了微软最近的一篇文章,详细介绍了它是如何实现的(到处都是旧的信息)。从文章本身:

The code sample uses the CLR 4 hosting APIs to host CLR in a native C++ project, load and invoke .NET assemblies

代码示例使用CLR 4托管api在本地c++项目中托管CLR,加载和调用。net程序集。

https://code.msdn.microsoft.com/CppHostCLR-e6581ee0

https://code.msdn.microsoft.com/CppHostCLR-e6581ee0

Basically it describes it in two steps:

基本上它分两个步骤来描述它:

  1. Load the CLR into a process
  2. 将CLR加载到一个进程中。
  3. Load your assembly.
  4. 加载程序集。