0

静的 C++ ライブラリをラップした CLR C++ dll があります。私は次のクラスを持っています:

#pragma once

#include <windows.h>
#include <sddl.h>

#include <LibEx.h>
using namespace System;
#using <mscorlib.dll>

namespace LIB_WrapperNamespace {

    public ref class LIB_WrapperClass
    {
    public:
        BOOL WINAPI T_LibEx_ConsoleConnect(IN DWORD num1, IN LPWSTR Name)
        {
            return LibEx_ConsoleConnect(num1,Name);
        }
        };
} 

C# では、ライブラリへの参照を追加します

LIB_WrapperNamespace.LIB_WrapperClass myLib = new LIB_WrapperNamespace.LIB_WrapperClass();

この関数を呼び出す方法、文字列を char* に送信する方法は? C#から:

string myName = "NAME";
myLib.T_LibEx_ConsoleConnect(1,**myName**);
4

2 に答える 2

2

API はそのパラメーターを として公開する必要があるwchar_t*ため、C# でポインター値を提供する必要があります。以下を試してください

IntPtr ptr = IntPtr.Zero;
try { 
  ptr = Marshal.StringToCoTaskMemUni("NAME");
  unsafe { 
    myLib.T_LibEx_Consoleconnect(1, (char*)(ptr.ToPointer()));
  }
} finally { 
  if (ptr != IntPtr.Zero) { 
    Marshal.FreeCoTaskMem(ptr);
  }
}

unsafe残念ながら、生のポインター値を使用してメソッドを公開しているため、コードなしで C# からこれを使用する方法はありません。別のアプローチは、たとえば a を受け取るオーバーロードを公開することstring^です。これは C# から使用でき、C++/CLI コードは からstring^へのマーシャリングを処理できます。LPWSTR

BOOL WINAPI T_LibEx_ConsoleConnect(DWORD num1, String^ Name) { 
   IntPtr ip = Marshal::StringToHGlobalUni(Name);
   BOOL ret = T_LibEx_ConsoleConnect(num1, static_cast<LPWSTR>(ip.ToPointer()));
   Marshal::FreeHGlobal(ip);
   return ret;
}

// From C#
myLib.T_LibEx_ConsoleConnect(1, "NAME");
于 2013-07-30T17:48:44.470 に答える
0

ラッパーのユーザーにマーシャリングの問題を「公開」するときに、C++\CLI プロジェクトをビルドして何かをラップするのはなぜですか? C++\CLI のアイデアは、マーシャリングの問題をラッパー内に隠すことです。関数を .NET 用にネイティブに宣言する必要があります。

#pragma once

#include <Windows.h>
#include <stdlib.h>
#include <string.h>
#include <msclr\marshal_cppstd.h> 
#include <vector>

namespace ClassLibrary2 {
public ref class Class1
{
public:
    //Expose .NET types to .NET users.
    System::Boolean T_LibEx_ConsoleConnect(System::UInt64 num1, System::String^ Name);
};

}

このラッパー関数を適切にマーシャリングすると、次のようになります。

#include "ClassLibrary2.h"

namespace ClassLibrary2 {
System::Boolean Class1::T_LibEx_ConsoleConnect(
    System::UInt64 num1, 
    System::String^ Name)
{
    //Initialize marshaling infrastructure. You can use its instance many times 
    //through out life span of your application.
    msclr::interop::marshal_context^ marshalContext = gcnew msclr::interop::marshal_context();

    //Turn System::String into LPWSTR. Keep in mind that you are now the owner of 
    //memory buffer allocated for unmanagedName. You need to release it somewhere.
    const wchar_t* clsConstChars = marshalContext->marshal_as<const wchar_t*>(Name);
    LPWSTR unmanagedName = const_cast<LPWSTR>(clsConstChars);

    //System::UInt64 num1 will be marshalled to DWORD natively by compiler.
    return LibEx_ConsoleConnect(num1, unmanagedName);
}}
于 2013-07-30T19:12:33.653 に答える