从C#用LPStr返回值调用C ++函数 [英] Calling C++ function with LPStr return value from C#

查看:82
本文介绍了从C#用LPStr返回值调用C ++函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个64位的C ++ dll,其中包含一个返回 LPStr 的函数.我想在C#中调用此函数.函数声明如下:

I have a C++ dll in 64-Bit, which contains a function that returns an LPStr. I would like to call this function in C#. The function declaration looks like this:

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

在我的C#代码中,我尝试了以下操作:

In my C# code I have tried the following:

 [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 退出,我什至无法尝试捕获异常.

I know that the function itself is good, as I can call it from another program (written in LabVIEW FWIW). But when I execute the C# Program, it just exits with error code 0x80000003, I can't even try, catch the exeption.

如何正确调用此函数?

作为副节点:我确实在此dll中还有其他功能,这些功能使用 LPStr 作为参数,可以毫无问题地调用它.只有两个返回 LPStr 的函数会出现问题

As a side node: I do have other functions in this dll, that use LPStr as parameters, which I can call without a problem. It is only two functions that return LPStr that make problems

推荐答案

如何正确调用此函数?

互操作吗?您不能...在纯C ++中它也容易出错

As interop? you can't ... it is also error prone in plain 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;
}

这篇关于从C#用LPStr返回值调用C ++函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆