Здравствуйте. Подскажите в чем проблема??
Вроде все правильно но вылетает ошибка.
Есть такая функция С++;
Надо обменятся с ней данными о домене.
extern "C" __declspec(dllexport) unsigned char ExchangeInfoDevice(int devIndex, int RW, string *domain, string *username, string *password, byte* containerpass, DWORD containerpasslen)
{
*domain = "123123123";
//*username = "adfasdfasdfasfasfsadfasdfw5e23452356236545623456";
//*password = "aasdfasfafasdfasdfasdfasdfasf";
containerpass[2] = containerpass[4] = 46;
return 123;
В шарпе извращаюсь как только можно.
static extern byte ExchangeInfoDevice(int devIndex, int RW, [MarshalAs(UnmanagedType.LPWStr)] ref string domain, [MarshalAs(UnmanagedType.LPWStr)] ref string username, [MarshalAs(UnmanagedType.LPWStr)] ref string password, byte[] containerpass, uint containerpasslen);
И реф передавал и указатель на неуправляемую память. Все равно либо ошибка AccessViolation либо еще куча всяких. А если ошибки не возникает то все равно передаваемые параметры своих значений не меняют.
Что я не так делаю то??
Возвращаемое значение буфера байтов меняется. И результат тоже правильный. Проблема только со строками.
AlexP
(Alex P.)
12.Май.2020 13:59:30
#2
WorldMaster:
string
Это std::string
или что?
Если да, то скорее всего всё сложно. Это ж класс, да еще и шаблон.
Если нельзя изменить функцию, чтоб она принимала char*
/wchar_t*
, то может быть как-то с помощью C++/CLI.
AlexP:
Это std::string
или что?
Ну да… он самый.
Ну можно наверное если подскажете как из этого стринга в чары сконверптить и обратно.
AlexP
(Alex P.)
12.Май.2020 14:24:16
#4
Если для возврата в C#, то .c_str()
+ strncpy
. В С принимать char* и размер, из C# StringBuilder.
var sb = new StringBuilder(2048);
MyCFunc(sb, sb.Capacity);
Если надо юникод, то в DllImportAttribute CharSet = CharSet.Unicode
и в С wchar_t
, std::wstring
, wcsncpy
.
WorldMaster:
обратно
конструктор. И из C# можно передавать просто string.
Ну видимо придется через прослойку делать. Для методов провайдера нужен именно такой тип. Не хочется переписывать рабочие версии сильно. Там итак дичь еще та. ))
AlexP
(Alex P.)
12.Май.2020 20:32:49
#6
Ну вообще если библиотека предназначена не только для С++, то API для её пользователей надо ограничивать до С (внутри ессно может использоваться С++), иначе никто не сможет её использовать )
Так что для этого бывает поверх С++ классов создают С API, где внутри их вызывают.
Либо для .NET еще есть вариант с C++/CLI — единственное норм применение этого языка )
https://www.google.com/search?q=c%2B%2B%2Fcli+c%2B%2B+wrapper
Сделал вот так:
extern "C" __declspec(dllexport) unsigned char ExchangeInfoDevice(int devIndex, int RW, char *domain, char *username, char *password, byte* containerpass, DWORD containerpasslen)
{
string domain_s(domain);
string username_s(username);
string password_s(password);
unsigned char result = ExchangeInfoDevice(devIndex, RW, &domain_s, &username_s, &password_s, containerpass, containerpasslen);
strcpy(domain, domain_s.c_str());
strcpy(username, username_s.c_str());
strcpy(password, password_s.c_str());
return result;
}
А в шарпе:
[DllImport("HIDComLibrary.dll", CallingConvention = CallingConvention.Cdecl)]
static extern byte ExchangeInfoDevice(int devIndex, int RW, [MarshalAs(UnmanagedType.LPStr)] StringBuilder domain, [MarshalAs(UnmanagedType.LPStr)] StringBuilder username, [MarshalAs(UnmanagedType.LPStr)] StringBuilder password, byte[] containerpass, uint containerpasslen);
StringBuilder strb = new StringBuilder("trololo", 1024);
StringBuilder strb2 = new StringBuilder("trololo", 1024);
StringBuilder strb3 = new StringBuilder("trololo", 1024);
var gh = ExchangeInfoDevice(0, 0, strb, strb2, strb3, cont, 24);
Все работает. И с латиницей и с кирилицей тоже.
AlexP
(Alex P.)
13.Май.2020 08:21:43
#8
В идеале надо принимать размер буфера параметром и использовать strcpy_s
, современные компиляторы обычно ругаются на не _s
функции.
Это не нужно вроде, у меня без этого работает.
AlexP:
размер буфера параметром
Да лениво как то уже … )) а ругань всегда можно заткнуть каким нибудь #define _CRT_SECURE_NO_WARNINGS