Вызов функции C ++ с возвращаемым значением LPStr из C # - PullRequest
0 голосов
/ 08 ноября 2018

У меня есть C ++ dll в 64-битном режиме, который содержит функцию, которая возвращает LPStr. Я хотел бы вызвать эту функцию в C #. Объявление функции выглядит так:

__declspec(dllexport) LPSTR __stdcall function(int16_t error_code);

В своем коде C # я пробовал следующее:

 [DllImport(@"<PathToInterface.dll>", EntryPoint = "function")]
 [return: MarshalAs(UnmanagedType.LPStr)]
 public static extern string function(Int16 error_code);

А потом в программе:

string ErrorMessage = "";
ErrorMessage = function(-10210);

Я знаю, что сама функция хороша, так как я могу вызвать ее из другой программы (написанной в LabVIEW FWIW). Но когда я запускаю C # -программу, она просто выходит с кодом ошибки 0x80000003, я даже не могу попытаться поймать исключение.

Как правильно вызвать эту функцию?

Как побочный узел: у меня есть другие функции в этой dll, которые используют LPStr в качестве параметров, которые я могу вызвать без проблем. Только две функции, возвращающие LPStr, создают проблемы

1 Ответ

0 голосов
/ 08 ноября 2018

Как правильно вызвать эту функцию?

Как взаимодействовать? Вы не можете ... это также подвержено ошибкам в простом C ++

лучше сделать это как

extern "C" __declspec(dllexport)  int __stdcall function(int16_t error_code, 
             LPSTR buffer, size_t size)
{
    LPCSTR format = "error: %i";
    size_t req = _scprintf(format, error_code); // check for require size
    if (req > size) //buffer size is too small
    {
        return req; //return required size
    }
    sprintf_s(buffer, size, format, error_code); //fill buffer 
    return 0;
}

И использование

class Program
{
    static void Main(string[] args)
    {
        short error_code = -10210;
        var ret = function(error_code, null, 0); // check for required size of the buffer
        var sb = new StringBuilder(ret); // create large enough buffer
        ret = function(error_code, sb, (uint)sb.Capacity + 1); //call again 
        var error_desc = sb.ToString(); //get results
        Console.WriteLine(error_desc);
        Console.ReadKey();
    }

    [DllImport("TestDll.dll", EntryPoint = "function", CharSet = CharSet.Ansi)]
    public static extern int function(short error_code, StringBuilder sb, int size);
}

использование в C ++

typedef int (__stdcall *function)(int16_t error_code, LPSTR buffer, size_t size);
int main()
{
    auto handle = LoadLibrary(L"TestDll.dll");
    auto proc = (function)GetProcAddress(handle, "_function@12"); 
    // of course it can be done via linking

    int16_t error_code = 333;
    const int ret = proc(error_code, NULL, 0); // check for size
    CHAR* buffer = new CHAR[ret + 1];
    //CHAR buffer[200]; //eventually allocate on stack 
    //but size have to be constant value and may be too small
    proc(error_code, buffer, ret+1); // call again 
    MessageBoxA(0, buffer, "Return", 0); //show result
    delete[] buffer; //free buffer!

    FreeLibrary(handle);
    return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...