[英]Passing a C# string to C++/CLI does not show the string value in the CPP program
我想通过CLI / C ++从C ++调用C#函数。
C#代码
private string _text = " ";
public void setText(string text)
{
// _text = text;
_text = "HI World";
}
理想情况下,setText应该仅包含注释行。 _text =“ HI World”是一个示例。
public string getText()
{
return _text;
}
C ++ / CLI代码
标头:
gcroot<Bridge> _managedObject;
virtual void setText(std::string text);
virtual std::string getText();
CPP文件
std::string CStringBridge::getText()
{
// _managedObject = gcnew Bridge(); 返回(marshal_as(_managedObject-> getText())); }
void CStringBridge::setText(std::string text)
{
// _managedObject = gcnew Bridge(); _managedObject-> setText(gcnew System :: String(text.c_str())); }
IStringBridgeWrapper* IStringBridgeWrapper::CreateInstance(void)
{
return ((IStringBridgeWrapper *)new CStringBridge());
}
注意:当我使用以下代码时
virtual void setText(System::String^ text);
virtual System::String^ getText();
我收到以下错误3395
* __ declspec(dllexport)不能应用于具有__clrcall调用约定的函数*
,所以我坚持使用std :: string
当我使用C ++ / CLI代码中的库并从我的C ++程序中调用时,应打印“ Hi World”; 相反,什么都没有打印
C ++控制台应用程序
IStringBridgeWrapper *pBridge = IStringBridgeWrapper::CreateInstance();
pBridge->setText(std::string("I am here"));
pBridge->getText();
我认为该字符串未正确传递。
任何解决它的想法将不胜感激。
编辑
我已经在注释后更新了代码,但是什么也没有显示。
gcroot创建一个句柄,但不为其分配内存。 但是由于Bridge没有分配内存,因此该应用程序无法正常工作。我的代码在本文的同一行中-http: //www.codeproject.com/Articles/10020/Using-managed-code-in-an-非托管应用程序 。
我想通过CLI / C ++从C ++调用C#函数。
等待...您想从C#调用C ++函数,对吧? 这就是C ++ / CLI的优点。 包装C ++代码以在托管环境中访问。 如果您真的想从C ++调用C#代码,则应考虑使用COM注册您的C#代码。 如果为此使用C ++ / CLI,则整个C ++程序将被拖入.NET世界,并且您可能从一开始就使用C#。
在C ++ / CLI中,您的ref(.NET)类的整个公共类接口应仅由托管类型组成。 那应该是System::String^
而不是std::string
。
COM是您的朋友:
在C#中创建接口
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
namespace CsharpLibrary
{
// Since the .NET Framework interface and coclass have to behave as
// COM objects, we have to give them guids.
[Guid("56A868B1-0AD4-11CE-B03A-0020AF0BA770"),
InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IStringHolder
{
String GetText();
void SetText(String s);
}
}
实现C#接口:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
namespace CsharpLibrary
{
[Guid("C6659361-1625-4746-931C-36014B146679")]
public class MyStringHolder : IStringHolder
{
String _text;
public String GetText()
{
return this._text;
}
public void SetText(String value)
{
_text = value;
}
}
}
从C ++创建并调用C#对象
#include <windows.h>
#include <stdio.h>
#pragma warning (disable: 4278)
// To use managed-code servers like the C# server,
// we have to import the common language runtime:
#import <mscorlib.tlb> raw_interfaces_only
#pragma warning (disable: 4278)
// To use managed-code servers like the C# server,
// we have to import the common language runtime:
#import <mscorlib.tlb> raw_interfaces_only
#import "..\CsharpLibrary\bin\Debug\CsharpLibrary.tlb" no_namespace named_guids
int main(int argc, char* argv[])
{
HRESULT hr = S_OK;
IStringHolder *pStringHolder = NULL;
//
// Initialize COM and create an instance of the InterfaceImplementation class:
//
CoInitialize(NULL);
hr = CoCreateInstance( __uuidof(MyStringHolder),
NULL,
CLSCTX_INPROC_SERVER,
__uuidof(IStringHolder),
reinterpret_cast<void**>(&pStringHolder));
if(SUCCEEDED(hr))
{
_bstr_t sHelloWorld = SysAllocString( L"Hello, World" );
hr = pStringHolder->SetText(sHelloWorld);
SysFreeString(sHelloWorld);
}
//
// Be a good citizen and clean up COM
//
CoUninitialize();
return hr;
}
在C#端,您必须生成类型库并通过构建后事件注册类:
生成类型库:“ $(FrameworkSDKDir)bin \\ NETFX 4.0 Tools \\ tlbexp.exe”“ $(TargetPath)” /out:"$(TargetDir)$(TargetName).tlb“
注册该类:C:\\ Windows \\ Microsoft.NET \\ Framework \\ v4.0.30319 \\ RegAsm.exe“ $(TargetPath)”
请享用!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.