AccessViolation, при вызове C ++ - DLL из C ++ / CLI - PullRequest
3 голосов
/ 09 декабря 2010

Я написал оболочку C ++ / CLI для C ++ - DLL, чтобы использовать эту DLL в программе на C #.

Однако, когда я вызываю функцию, которая принимает символ *, я получаю AccessViolation

int Wrapper::Net_methodX(int a, String^ key, long v)
{
    IntPtr ptr = Marshal::StringToHGlobalAnsi(key);
    pin_ptr<char> cKey = static_cast<char*>(ptr.ToPointer());
    int val = methodX(a,cKey, v); // AccessViolation here

    Marshal::FreeHGlobal(ptr);
    return val;
}

Подпись функции C ++:

int methodX(int a, char *Key, long v);

РЕДАКТИРОВАТЬ 1

Просто «закрепить», как показано ниже, неработать либо:

int Wrapper::Net_methodX(int a, String^ key, long v)
{
    IntPtr ptr = Marshal::StringToHGlobalAnsi(key);
    char* cKey = static_cast<char*>(ptr.ToPointer());
    pin_ptr<char> pinned = cKey;
    int val = methodX(a,cKey, v);

    Marshal::FreeHGlobal(ptr);
    return val;
}

РЕДАКТИРОВАТЬ 1 КОНЕЦ

РЕДАКТИРОВАТЬ 2

Я также пытался PtrToStringChars следующим образом (СпасибоМэтт, нашел также некоторые документы здесь ):

int Wrapper::Net_methodX(int a, String^ key, long v)
{
    pin_ptr<const wchar_t> wkey = PtrToStringChars(key);

    size_t convertedChars = 0;
    size_t  sizeInBytes = ((key->Length + 1) * 2);
    errno_t err = 0;
    char * ckey = (char * ) malloc(sizeInBytes);

    err = wcstombs_s(&convertedChars, ckey, sizeInBytes, wkey, sizeInBytes);

    int val = methodX(A_Symbol_Table,ckey, Value);

    return val;
}

AccessViolation по-прежнему происходит, возможно, это ошибка в methodX () (который является сторонней DLL).

РЕДАКТИРОВАТЬ 2 КОНЕЦ

Я прочитал здесь несколько связанных вопросов, но пока не нашел решения.

Есть какие-нибудь подсказки?Спасибо.

Ответы [ 3 ]

2 голосов
/ 14 мая 2015

Я знаю, что это старый вопрос, но для тех, кто наткнулся на этот вопрос в поисках ответа, вот несколько простых решений.

  1. Просто используйте sprintf, чтобы сделать преобразование, подобное этому: sprintf(cStr, "%s", clrString);.См. мой ответ на этот вопрос для полного примера.
  2. Прочитайте KB311259 , как предложено Мэттом Смитом.Если вы используете VS 2008 или выше, используйте marshal_as<> (Метод № 4 в КБ).Это намного проще, чем другие методы в этом документе.
0 голосов
/ 10 декабря 2010

Саймон, я опробовал твой пример и не получил нарушения прав доступа.Вот мой код:

using namespace System;
using namespace System::Runtime::InteropServices;

ref class Wrapper
{
public:
    static int Net_methodX(int a, String^ key, long v);
};

int methodX(int a, char * pKey, long v)
{
    IntPtr ptr = static_cast<IntPtr>(pKey);
    String ^ pString = Marshal::PtrToStringAnsi(ptr);
    System::Console::WriteLine(pString);
    return a;
}

int Wrapper::Net_methodX(int a, String^ pKey, long v)
{     
    IntPtr ptr = Marshal::StringToHGlobalAnsi(pKey);     
    pin_ptr<char> cKey = static_cast<char*>(ptr.ToPointer());     
    int val = methodX(a,cKey, v); // AccessViolation here      
    Marshal::FreeHGlobal(ptr);     
    return val; 
}

void main()
{
    Wrapper wrapper;
    String ^ p = gcnew String("Hello");
    wrapper.Net_methodX(0, p, 0);
}

Также у меня есть несколько комментариев:

  1. Читайте здесь: http://support.microsoft.com/kb/311259
  2. Вы используете pin_ptrна родную память.Метод StringToHGlobalAnsi возвращает собственную память, поэтому я не думаю, что использование pin_ptr имеет здесь смысл.Pin_ptr будет иметь смысл, если вы используете метод, который возвращает вам указатель на управляемую память (например, PtrToStringChars).Если вы не изменяете строку, вы, вероятно, все равно захотите использовать подход PtrToStringChars - чтобы избежать ненужного выделения и копирования.
  3. Не могли бы вы опубликовать примерную версию methodX, которая вызывает проблему?Если я смогу воспроизвести проблему, я смогу быть более полезным.
0 голосов
/ 09 декабря 2010

Simon

Я думаю, что есть проблема со следующим кодом

pin_ptr<char> cKey = static_cast<char*>(ptr.ToPointer());

Возможно, вы захотите прочитать это http://social.msdn.microsoft.com/forums/en-US/vclanguage/thread/0bd049fe-844a-4cb6-b9f6-c8f5107bc957

Дайте мне знать, помогло ли это вам.

Sujay

...