托管C++;在c#和c+之间架起一座桥梁+; 我有点生疏了,实际上我的C++真的生锈了。从大学一年级就没碰过它,所以已经有一段时间了

托管C++;在c#和c+之间架起一座桥梁+; 我有点生疏了,实际上我的C++真的生锈了。从大学一年级就没碰过它,所以已经有一段时间了,c#,clr,c++-cli,unmanaged,C#,Clr,C++ Cli,Unmanaged,不管怎样,我做的和大多数人做的相反。用C++调用C代码。我在网上做了一些研究,看起来我需要创建一些管理C++来形成一个桥梁。使用uu declspec(dllexport),然后从中创建一个dll,并将整个内容用作包装器 但我的问题是——我真的很难找到例子。我发现了一些基本的东西,其中有人想使用C版本来String.ToUpper(),但这是非常基本的,只是一个小的代码片段 有人知道我在哪里可以找到更具体的东西吗?注意,我不想使用COM。我们的目标是完全不接触C代码。在visual studio

不管怎样,我做的和大多数人做的相反。用C++调用C代码。我在网上做了一些研究,看起来我需要创建一些管理C++来形成一个桥梁。使用uu declspec(dllexport),然后从中创建一个dll,并将整个内容用作包装器

但我的问题是——我真的很难找到例子。我发现了一些基本的东西,其中有人想使用C版本来String.ToUpper(),但这是非常基本的,只是一个小的代码片段


有人知道我在哪里可以找到更具体的东西吗?注意,我不想使用COM。我们的目标是完全不接触C代码。

在visual studio中创建一个新的C++/CLI项目,并添加对C#dll的引用。假设我们有一个名为
DotNetLib.dll的C#dll,该类位于:

namespace DotNetLib
{
    public class Calc
    {
        public int Add(int a, int b)
        {
            return a + b;
        }
    }
}

现在将CCL+C++类添加到C++ /CLI项目:

// TestCPlusPlus.h

#pragma once

using namespace System;
using namespace DotNetLib;

namespace TestCPlusPlus {

    public ref class ManagedCPlusPlus
    {
    public:
        int Add(int a, int b)
        {
            Calc^ c = gcnew Calc();
            int result = c->Add(a, b);
            return result;
        }
    };
}

这将调用C++中的C ^。

如果需要,可以向C++ + CLI项目添加一个本地C++类,它可以与CLR C++类对话:

// Native.h
#pragma once

class Native
{
public:
    Native(void);
    int Add(int a, int b);
    ~Native(void);
};
以及:

你应该能够调用任何其他原生的C++类的原生类。

注意到,托管C++与C++/CLI不同,并被C++所取代。维基百科对此进行了最好的解释:


当莱恩抢先写了一个例子时,我无论如何都会把它贴出来,以防万一

编写包装器以访问您自己的库的过程与访问标准.Net库的过程相同

一个名为CsharpProject的项目中的C#类代码示例:

using System;

namespace CsharpProject {
    public class CsharpClass {
        public string Name { get; set; }
        public int Value { get; set; }

        public string GetDisplayString() {
            return string.Format("{0}: {1}", this.Name, this.Value);
        }
    }
}

您将创建一个托管C++类库项目(示例是CsHARPrPrAPER),并将您的C.CyProject添加到它中作为参考。为了在内部和引用项目中使用相同的头文件,您需要一种使用右declspec的方法。这可以通过定义预处理器指令(

CSHARPWRAPPER\u EXPORTS
)并使用
\ifdef
在头文件的C/C++接口中设置导出宏来实现。非托管接口头文件必须包含非托管内容(或由预处理器过滤掉)

非托管C++接口头文件(CPPPoalth.h):

然后您只需编写完成包装的接口代码

托管C++接口源文件(CPPPoald.CPP):

然后只需将非托管头包含在非托管项目中,告诉链接器在链接时使用生成的.lib文件,并确保.Net和包装DLL与非托管应用程序位于同一文件夹中

#include <stdlib.h>

// Include the wrapper header
#include "CppInterface.h"

void main() {
 // Call the unmanaged wrapper function
 std::string strDisplayString = GetDisplayString("Test", 123);

 // Do something with it
 printf("%s\n", strDisplayString.c_str());
}
#包括
//包括包装头
#包括“CppInterface.h”
void main(){
//调用非托管包装器函数
std::string strDisplayString=GetDisplayString(“测试”,123);
//用它做点什么
printf(“%s\n”,strDisplayString.c_str());
}

您想向非托管C/C++公开的界面有多复杂?请参阅此链接以获取类似的问题/答案:。您解释得更详细了-希望我可以选择这两个答案。谢谢字符串就是一个很好的例子,因为只要您需要将字符串从本机整理为托管(在大多数互操作中通常很快就会这样!),对于“没有这样的文件或目录”,就需要使用转换函数:1)将
cppfinterface.h
添加到非托管应用程序。如果所有项目都位于同一位置/存储库中,我不会这样做。因为您需要维护重复的文件。2) 将路径添加到非托管应用程序的compile include文件夹下的包装器项目文件。对于Visual Studio,右键单击项目并选择“属性”。然后在“配置属性”->“C/C++”->“常规”->“其他包含目录”下,添加到
cppeinterface.h
位置的路径。只需一件小事:当您找不到.lib文件并且链接器正在哭泣时,可能是因为您没有向类中添加“#定义导出"规范"declspec(dllexport)”。
#pragma once

#include <string>

// Sets the interface function's decoration as export or import
#ifdef CSHARPWRAPPER_EXPORTS 
#define EXPORT_SPEC __declspec( dllexport )
#else
#define EXPORT_SPEC __declspec( dllimport )
#endif

// Unmanaged interface functions must use all unmanaged types
EXPORT_SPEC std::string GetDisplayString(const char * pName, int iValue);
#pragma once

#include <string>

// .Net System Namespaces
using namespace System;
using namespace System::Runtime::InteropServices;

// C# Projects
using namespace CsharpProject;


//////////////////////////////////////////////////
// String Conversion Functions

inline
String ^ ToManagedString(const char * pString) {
 return Marshal::PtrToStringAnsi(IntPtr((char *) pString));
}

inline
const std::string ToStdString(String ^ strString) {
 IntPtr ptrString = IntPtr::Zero;
 std::string strStdString;
 try {
  ptrString = Marshal::StringToHGlobalAnsi(strString);
  strStdString = (char *) ptrString.ToPointer();
 }
 finally {
  if (ptrString != IntPtr::Zero) {
   Marshal::FreeHGlobal(ptrString);
  }
 }
 return strStdString;
}
#include "CppInterface.h"
#include "CsharpInterface.h"

std::string GetDisplayString(const char * pName, int iValue) {
 CsharpClass ^ oCsharpObject = gcnew CsharpClass();

 oCsharpObject->Name = ToManagedString(pName);
 oCsharpObject->Value = iValue;

 return ToStdString(oCsharpObject->GetDisplayString());
}
#include <stdlib.h>

// Include the wrapper header
#include "CppInterface.h"

void main() {
 // Call the unmanaged wrapper function
 std::string strDisplayString = GetDisplayString("Test", 123);

 // Do something with it
 printf("%s\n", strDisplayString.c_str());
}