托管C ++,形成C#和C之间的桥梁++ [英] Managed C++ to form a bridge between c# and C++

查看:111
本文介绍了托管C ++,形成C#和C之间的桥梁++的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有点生疏,居然真的跟我的C ++生锈。所以它已经有一段时间大学大一的时候还没有触及它。

I'm a bit rusty, actually really rusty with my C++. Haven't touched it since Freshman year of college so it's been a while.

反正我在做什么的大多数人则相反。从调用C ++ C#代码。我已经在网上做了一些研究,好像我需要创建一些托管C ++,形成一个桥梁。 。使用__declspec(dllexport)的,然后从创建一个DLL,并使用整个事情作为一个包装

Anyway, I'm doing the reverse of what most people do. Calling C# code from C++. I've done some research online and it seems like I need to create some managed C++ to form a bridge. Use __declspec(dllexport) and then create a dll from that and use the whole thing as a wrapper.

但我的问题是 - 我真的有一个很难找到例子。我发现如果有人想用C#版本String.ToUpper(),但是这是很基本的,只是一个很小的代码片段一些基本的东西。

But my problem is - I'm really having a hard time finding examples. I found some basic stuff where someone wanted to use the C# version to String.ToUpper() but that was VERY basic and was only a small code snippet.

任何人有什么在那里我可以找一些更具体的想法?请注意,我不想使用COM。我们的目标是不碰的C#代码都没有。

Anyone have any ideas of where I can look for something a bit more concrete? Note, I do NOT want to use COM. The goal is to not touch the C# code at all.

推荐答案

虽然LAIN打我写一个例子,我会发布它好歹以防万一......

While lain beat me to writing an example, I'll post it anyhow just in case...

写的包装来访问自己的库的过程是一样的访问标准的.NET库之一。

The process of writing a wrapper to access your own library is the same as accessing one of the standard .Net libraries.

Example C# class code in a project called CsharpProject:

实例C#类在一个名为CsharpProject项目代码系统;

命名空间CsharpProject {
公共类CsharpClass {
公共字符串名称{;组; }
公共int值{搞定;组; }

公共字符串GetDisplayString(){
返回的String.Format({0}:{1},this.Name,THIS.VALUE);
}
}
}

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 ++类库项目(例如是CsharpWrapper),并添加你的C#项目作为它的一个引用。为了使用相同的头文件供内部使用,在引用的项目,你需要一种方法来使用权declspec。这可以通过定义(在这种情况下, CSHARPWRAPPER_EXPORTS )一个预处理指令,并做到用一个 #IFDEF 来设置导出宏在C / C ++在头文件中的接口。 。非托管接口头文件必须包含非托管的东西(或把它过滤掉由预处理器)

You would create a managed C++ class library project (example is CsharpWrapper) and add your C# project as a reference to it. In order to use the same header file for internal use and in the referencing project, you need a way to use the right declspec. This can be done by defining a preprocessor directive (CSHARPWRAPPER_EXPORTS in this case) and using a #ifdef to set the export macro in your C/C++ interface in a header file. The unmanaged interface header file must contain unmanaged stuff (or have it filtered out by the preprocessor).

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

Unmanaged C++ Interface Header file (CppInterface.h):

#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);



然后你可以创建一个内部的头文件能在您的托管库文件包含。这将增加使用命名空间语句,可以包含你需要的辅助功​​能。

Then you can create an internal header file to be able to include in your managed library files. This will add the using namespace statements and can include helper functions that you need.

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

Managed C++ Interface Header file (CsharpInterface.h):

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



然后你只写你的界面代码,做包装。

Then you just write your interface code that does the wrapping.

托管C ++接口源文件(CppInterface.cpp):

Managed C++ Interface Source file (CppInterface.cpp):

#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());
}



然后,只需在您的非托管项目中的非托管的头,告诉链接器使用链接时,并确保.Net和包装的DLL都在同一个文件夹作为非托管应用程序生成的.lib文件。

Then just include the unmanaged header in your unmanaged project, tell the linker to use the generated .lib file when linking, and make sure the .Net and wrapper DLLs are in the same folder as your unmanaged application.

#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());
}

这篇关于托管C ++,形成C#和C之间的桥梁++的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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