2009-06-24 5 views
4

У меня есть следующая функция CВызов C++ функция из C#

void FillAndReturnString(char ** someString) 
{ 
    char sourceString[] = "test"; 
    *someString = new char[5]; 
    memcpy(*someString, sourceString, 5); 
} 

++ Он объявлен как

extern "C" 
{ 
__declspec(dllexport) void __cdecl FillAndReturnString(char ** someString); 
} 

Как назвать эту функцию из C#?

Благодаря

ответ

1

С P/Invoke.

+0

Это не очень специфичны. – sblom

+0

Нет, это не так. Но исходный вопрос не сказал, что он уже пробовал, и с какими проблемами он столкнулся, поэтому я действительно не могу уточнить. Но урок, к которому я привязался, вникает в детали. –

1

Вам необходимо знать, что вы выделяете неуправляемый блок памяти в своей функции C++, поэтому невозможно передать управляемый объект String или Array из кода C# в «удерживать» массив символов.

Один из подходов - определить функцию «Удалить» в вашей родной DLL и вызвать ее для освобождения памяти. На управляемой стороне вы можете использовать структуру IntPtr, чтобы временно удерживать указатель на массив символов C++.

// c++ function (modified) 
void __cdecl FillAndReturnString(char ** someString) 
{ 
    *someString = new char[5]; 
    strcpy_s(*someString, "test", 5); // use safe strcpy 
} 

void __cdecl DeleteString(char* someString) 
{ 
    delete[] someString 
} 


// c# class 
using System; 
using System.Runtime.InteropServices; 

namespace Example 
{ 
    public static class PInvoke 
    { 
     [DllImport("YourDllName.dll")] 
     static extern public void FillAndReturnString(ref IntPtr ptr); 

     [DllImport("YourDllName.dll")] 
     static extern public void DeleteString(IntPtr ptr); 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
     IntPtr ptr = IntPtr.Zero; 
     PInvoke.FillAndReturnString(ref ptr); 

     String s = Marshal.PtrToStringAnsi(ptr); 

     Console.WriteLine(s); 

     PInvoke.Delete(ptr); 
     } 
    } 

}

+0

Вы также можете использовать char * в C# (не совместимый с CLI, но вы можете сделать больше с помощью введенного указателя, а затем с помощью IntPtr), но только если вы используете wchar_t на стороне C++. И его действительно не важно, что удерживание переменной является временным. Разумеется, если вы оставите неуправляемую память в управляемом объекте, вам придется знать об этом и удалять, когда это необходимо, но нет ничего особенного в том, что касается CLR. – Hippiehunter

+0

Взорвав на PInvoke.FillAndReturnString (ref ptr) – 2009-06-25 14:52:35

+0

MHM - Исправлено ли какое-либо исключение? Если да, то что говорит ошибка? Убедитесь, что код C++ окружен extern «C», а C++ .dll находится в том же месте, что и C# .exe. И, есть хороший шанс, что я пропустил что-то в своем коде, конечно. – Kei