2013-07-30 3 views
0

У меня есть CLR C++ dll, которая нарушила статическую библиотеку C++. У меня есть следующий класс:вызов функции C++ с char * с C#

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

Теперь, как вызвать эту функцию, как отправить строку на символ *? из C#:

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

изменения в характере array – Saksham

+1

Вы можете просто передать его как 'string' - Marshaller обработает превращение его в char * для вас. –

+0

@ Сакшам, как это поможет? Он определяет это в собственном коде, если он использовал собственный массив, он все равно будет отображаться как значение указателя – JaredPar

ответ

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

К сожалению, хотя, так как вы выставили метод с сырым значением указателя не существует никакого способа, чтобы использовать эту функцию из C# без unsafe кода. Альтернативный подход заключался бы в том, чтобы разоблачить перегрузку, которая принимает, например, 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"); 
+0

Я получаю erro: Аргумент 2: невозможно преобразовать из 'System.IntPtr' в 'char * ' – Joseph

+0

@Joseph ах, вам понадобилось использовать небезопасный код и использовать метод 'IntPtr :: ToPointer'. – JaredPar

+0

@Joseph Я обновил свой ответ, чтобы исправить преобразование указателя и предоставить альтернативу, которая не требует какого-либо небезопасного кода – JaredPar

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); 
}} 
+0

Большое спасибо, но я не смог скомпилировать ClassLibrary2, я получаю эту ошибку: ошибка C4996: 'msclr :: interop :: error_reporting_helper <_To_Type, _From_Type> :: marshal_as': Это преобразование не поддерживается библиотекой или заголовком файл, необходимый для этого преобразования, не включен. Пожалуйста, обратитесь к документации по «Как: Расширить библиотеку Marshaling» для добавления собственного метода маршалинга. – Joseph

+0

Извините за задержку. Действительно, marshal_context не принимает LPWSTR как общий аргумент, мой плохой. Я заменил вызов на wchar_t *. –

Смежные вопросы