1

CLI / C++を介してC++からC#関数を呼び出したい。

C#コード

private string _text = " ";

public void setText(string text)
{
    // _text = text;
    _text = "HI World";
}

理想的には、setTextにはコメント行のみを含める必要があります。_text="HIWorld"はその一例です。

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(); return(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 ++プログラムから呼び出すと、「HiWorld」が出力されます。代わりに何も印刷されません

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- unmanaged-application

4

2 に答える 2

0

CLI / C++を介してC++からC#関数を呼び出したい。

待ってください...C#からC ++関数を呼び出したいですよね?それがC++/CLIに適しています。管理された環境でアクセスできるようにC++コードをラップします。本当にC++からC#コードを呼び出したい場合は、C#コードを登録するCOMを調べる必要があります。これにC++/ CLIを使用すると、C ++プログラム全体が.NETの世界にドラッグされ、最初からC#を使用できたはずです。

C ++ / CLIでは、ref(.NET)クラスのパブリッククラスインターフェイス全体は、マネージ型のみで構成されている必要があります。それはSystem::String^の代わりになりstd::stringます。

于 2013-03-26T15:28:45.063 に答える
0

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

楽しみ!

于 2013-03-26T16:58:38.177 に答える