Выделение строки из c # в c ++ - PullRequest
0 голосов
/ 19 января 2011

Я новичок в мире Microsoft.У меня много проблем при попытке передать простую строку из c # в dll / c ++. Я прочитал много постов и документации, но проблема та же.

C ++ code

extern "C" __declspec(dllexport) int Init( long l , char* url );

C # код

[DllImport("MCRenderer.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = false)]
    public static extern int Init(long a, StringBuilder url);


Init(hndl.ToInt64(), str );

что происходит, когда длинное значение передается правильно, в то время как строковый параметр

0x00000000 <Bad Ptr>

можете ли вы мне помочь ... Я действительно растерялся, спасибо !!AG

Ответы [ 4 ]

2 голосов
/ 19 января 2011

Это потому, что вы неправильно пишете: long и int в C ++ (обычно) int в C #.

1 голос
/ 19 января 2011

Вы должны передать строку, URL должен иметь тип string, а не StringBuilder.

0 голосов
/ 19 января 2011

Попробуйте использовать LPCSTR в параметре функции dll

extern "C" __declspec(dllexport) int Init( long l , **LPCTSTR** url );

Вот хороший пример того, как это сделать.

C ++:

extern "C" __declspec(dllexport) void doSomething(LPCTSTR asString)
{
    std::cout << "here" << (wchar_t)asString << endl;
    system ("pause");
}

C #:

class Program
{
    static void Main(string[] args)
    {
        String myString = "String in C#";
        doSomething(myString);
    }
    private const String path = @"C:\testdll2.dll"; //Make sure that the DLL is in this location

    [DllImport(path)]
    private static extern void doSomething(string asString);
}
0 голосов
/ 19 января 2011

С MSDN , вам необходимо:

Единственное предостережение в том, что StringBuilder должен быть выделен достаточно места для возвращаемого значения, или текст будет переполнен, вызывая исключение P / Invoke

Также из Маршалинг между управляемым и неуправляемым кодом

  • Не передавайте StringBuilder по ссылке (используя out или ref). В противном случае CLR будет ожидать, что сигнатура этого аргумента будет wchar_t ** вместо wchar_t *, и не сможет закрепить внутренний буфер StringBuilder. Производительность будет значительно ухудшена.
  • Используйте StringBuilder, когда неуправляемый код использует Unicode. В противном случае CLR придется сделать копию строки и преобразовать ее между Unicode и ANSI, что приведет к снижению производительности. Обычно вы должны маршалировать StringBuilder как LPARRAY символов Unicode или как LPWSTR.
  • Всегда заранее указывайте емкость StringBuilder и убедитесь, что емкость достаточно велика для размещения буфера. Лучшая практика на стороне неуправляемого кода - принять размер строкового буфера в качестве аргумента, чтобы избежать переполнения буфера. В COM вы также можете использовать size_is в IDL для указания размера.

Итак, в вашем примере вам нужно указать собственный размер в качестве параметра StringBuilder, например: StringBuilder str = new StringBuilder(SIZE_OF_NATIVE_STRING);

...