加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

管理C形成c#和C之间的桥梁

发布时间:2020-12-16 07:54:10 所属栏目:百科 来源:网络整理
导读:我有点生锈,其实真的生锈了我的C.自从大一学年以来,没有碰到过,所以已经有一段时间了. 无论如何,我正在做大多数人做的事情.从C调用C#代码.我在网上做了一些研究,似乎我需要创建一些管理C来形成桥梁.使用__declspec(dllexport),然后创建一个dll,并将整个东西
我有点生锈,其实真的生锈了我的C.自从大一学年以来,没有碰到过,所以已经有一段时间了.

无论如何,我正在做大多数人做的事情.从C调用C#代码.我在网上做了一些研究,似乎我需要创建一些管理C来形成桥梁.使用__declspec(dllexport),然后创建一个dll,并将整个东西作为一个包装器.

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

任何人都有什么想法可以在哪里寻找更具体的东西?注意,我不想使用COM.目标是不要碰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类库项目(例如CsharpWrapper),并添加您的C#项目作为参考.为了使用相同的头文件进行内部使用和引用项目,您需要一种使用正确的declspec的方法.这可以通过定义预处理器指令(在这种情况下为CSHARPWRAPPER_EXPORTS)并使用#ifdef在头文件中的C/C++接口中设置导出宏来完成.非管理的接口头文件必须包含非托管的东西(或者由预处理器滤除).

非管理C接口头文件(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);

然后,您可以创建一个内部头文件,以便能够包含在托管库文件中.这将添加using namespace语句,并且可以包括您需要的帮助器函数.

管理C接口头文件(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;
}

然后你只需编写你的接口代码来做包装.

托管C接口源文件(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());
}

然后在非托管项目中包含非托管头,告诉链接器在链接时使用生成的.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("%sn",strDisplayString.c_str());
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读