У меня есть приложение С#, которое обращается к функциям из неуправляемой библиотеки C++ с использованием CLI DLL. Моя проблема заключается в том, что я не могу получить текст из библиотеки C++, который будет правильно передан в приложение С#. Код, который я имею до сих пор, выглядит следующим образом:
С#
[DllImport("Wrapper.dll", EntryPoint = "GetNameLength", CallingConvention = CallingConvention = CallingConvention.Cdecl)]
public static extern bool _GetNameLength( int index, out int size);
[DllImport("Wrapper.dll", CharSet = CharSet.Ansi, EntryPoint = "GetName", CallingConvention = CallingConvention.Cdecl)]
public static extern bool _GetName( out Stringbuilder name, int size, int index);
private void TestFunction()
{
int size = 0;
_GetNameLength(2, out size);
StringBuilder str = new StringBuilder(size + 1);
_GetName(out str, str.Capacity, 2);
btnName.Text = str.ToString();
}
CLI
// In the header.
#define DllExport __declspec( dllexport)
extern "C" {
DllExport bool __cdecl GetNameLength( int index, int& size);
DllExport bool __cdecl GetName( char* name, int size, int index);
};
// In the '.cpp'.
bool __cdecl GetNameLength( int index, int& size) {
if( gp_app == nullptr)
return false;
gp_app->GetNameLength( index, size);
return true;
}
bool __cdecl GetName( char* name, int index, int size) {
if( gp_app == nullptr)
return false;
const char* n = "";
n = gp_app->GetName( index);
name = new char[size];
strcpy( name, n);
return true;
}
C++
// In the header.
class App {
void GetNameLength( int index, int& size);
const char* GetName( int index);
};
// In the '.cpp'.
void App::GetNameLength( int index, int& size) {
if( index >= 0 && index < gs_namesCount)
size = strlen( gs_names[index]);
}
const char* App::GetName( int index) {
if( index >= 0 && index < gs_namesCount)
return gs_names[index];
return nullptr;
}
Я могу отлаживать DLL, и я видел, что он правильно копирует имя, даже когда я просто использую name = const_cast<char*>( n)
(и когда я использую строку вместо StringBuilder) но по какой-то причине это значение не возвращается к С# из DLL.
Я читал, что возможная причина заключается в том, что C++ может использовать символы ASCII, в то время как С# использует 16-битные символы, и что исправление для этого должно включать CharSet = CharSet.Ansi
чтобы оно правильно упорядочивалось, когда оно возвращалось на С#, но это видимо, не помогло.
Может ли кто-нибудь сказать мне, что я делаю неправильно?
Решение:
Используйте public ref class
вместо пространства имен и объявляйте функции, используя void Foo( [Out] String^ %name)
гарантируя, что using namespace System::Runtime::InteropServices;
Включено.
Это говорит мне, что у вас есть управляемая DLL c++.
if( gp_app == nullptr)
return false;
Если это так, вы можете экспортировать управляемый класс и использовать параметр String как метод.
Проверьте это: http://msdn.microsoft.com/library/windows/apps/hh699870.aspx
String
и StringBuilder
качестве параметров в моей оболочке, однако это означало, что я не смог назначить его с помощью __cdecl
(мне пришлось использовать __clrdecl
, я так думаю), что означало, что его нельзя было экспортировать для использования в моем Код C #
GetName
в вашей части C ++ (один занимает один аргумент, два других).ref class
и вы можете использовать его так же, как C #.