2008-10-18 2 views
3

У меня есть функция в CPP со следующим прототипом:C# вызывая функцию CPP с неизвестным количеством аргументов из CPP

char* complexFunction(char* arg1, ...); 

я импортировать его из C# с помощью атрибута DllImport. вопросы: Как определить прототип в C# (под атрибутом DLLImport)? Как передать аргументы этой функции? спасибо

ответ

3

Это называется вариационной функцией. Информация о поддержке P/Invoke для них довольно скудна, вот что я узнал.

Я не мог найти способ напрямую DllImport функция с переменным числом аргументов. Мне пришлось DllImportвсе варианты аргументов как разные перегрузки.

Возьмем, к примеру, wsprintf. Она имеет следующий прототип в winuser.h:

int WINAPIV wsprintf(  
    LPTSTR lpOut, 
    LPCTSTR lpFmt, 
    ...); 

Он может быть использован из C#, как это:

using System; 
using System.Text; 
using System.Runtime.InteropServices; 

class C { 

    // first overload - varargs list is single int 
    [DllImport("user32.dll", CallingConvention=CallingConvention.Cdecl)] 
    static extern int wsprintf(
    [Out] StringBuilder buffer, 
    string format, 
    int arg); 

    // second overload - varargs list is (int, string) 
    [DllImport("user32.dll", CallingConvention=CallingConvention.Cdecl)] 
    static extern int wsprintf(
    [Out] StringBuilder buffer, 
    string format, 
    int arg1, 
    string arg2); 

    public static void Main() { 
    StringBuilder buffer = new StringBuilder(); 
    int result = wsprintf(buffer, "%d + %s", 42, "eggs!"); 
    Console.WriteLine("result: {0}\n{1}", result, buffer); 
    } 
} 

Теперь для решения вашей complexFunction.

char* complexFunction(char* arg1, ...); 

Его список varargs должен быть адресован таким же образом: путем предоставления всех полезных перегрузок. Но есть и другое осложнение - тип возврата. Я предполагаю, что complexFunction выделяет и возвращает массив char. В этом случае, скорее всего, вызывающий отвечает за освобождение массива. Для этого вы также должны импортировать процедуру перераспределения, назовем ее void free(void*).

Предполагая, что все, что предполагалось, C# код, использующий complexFunction будет выглядеть следующим образом:

using System; 
using System.Text; 
using System.Runtime.InteropServices; 

class C { 

    [DllImport("your.dll", 
      CallingConvention=CallingConvention.Cdecl, 
      CharSet=CharSet.Ansi)] 
    static extern IntPtr complexFunction(
    string format, 
    int arg1, int arg2); 

    [DllImport("your.dll", CallingConvention=CallingConvention.Cdecl)] 
    static extern void free(IntPtr p); 

    public static void Main() { 
    IntPtr pResult = complexFunction("%d > %s", 2, 1); 
    string sResult = Marshal.PtrToStringAnsi(pResult); 
    free(pResult); 
    Console.WriteLine("result: {0}", sResult); 
    } 
} 
0

благодаря Constantin, прототип функции CPP не может быть изменен. он должен быть extern «C» __declspec (dllexport) char * myFunc (char *, ...);

Есть ли способ вызвать его из C# с помощью DLLImport?

спасибо большое!

+0

Я немного расширил свой ответ. – Constantin 2008-10-18 20:50:31

Смежные вопросы