将字符串从DLL传递到C#

Passing a string from a DLL to C#

本文关键字:DLL 字符串      更新时间:2023-10-16

我有一个C#应用程序,该应用程序使用CLI DLL从非托管的C Libary访问功能。我的问题是,我无法从C 库中获取短信,可以正确传递到C#应用程序。到目前为止,我的代码如下:

c#

[DllImport("Wrapper.dll", EntryPoint = "GetNameLength", CallingConvention = CallingConvention = CallingConvention.Cdecl)]
public static extern bool _GetNameLength( int index, out int size);
[DllImport("Wrapper.dll", CharSet = CharSet.Ansi, EntryPoint = "GetName", CallingConvention = CallingConvention.Cdecl)]
public static extern bool _GetName( out Stringbuilder name, int size, int index);
private void TestFunction()
{
    int size = 0;
    _GetNameLength(2, out size);
    StringBuilder str = new StringBuilder(size + 1);
    _GetName(out str, str.Capacity, 2);
    btnName.Text = str.ToString();
}

cli

// In the header.
#define DllExport __declspec( dllexport)
extern "C" {
    DllExport bool __cdecl GetNameLength( int index, int& size);
    DllExport bool __cdecl GetName( char* name, int size, int index);
};

// In the '.cpp'.
bool __cdecl GetNameLength( int index, int& size) {
    if( gp_app == nullptr)
        return false;
    gp_app->GetNameLength( index, size);
    return true;
}
bool __cdecl GetName( char* name, int index, int size) {
    if( gp_app == nullptr)
        return false;
    const char* n = "";
    n = gp_app->GetName( index);
    name = new char[size];
    strcpy( name, n);
    return true;
}

C

// In the header.
class App {
    void GetNameLength( int index, int& size);
    const char* GetName( int index);
};
// In the '.cpp'.
void App::GetNameLength( int index, int& size) {
    if( index >= 0 && index < gs_namesCount)
        size = strlen( gs_names[index]);
}
const char* App::GetName( int index) {
    if( index >= 0 && index < gs_namesCount)
        return gs_names[index];
    return nullptr;
}

我能够调试DLL,并且我已经看到它确实正确地复制了名称,即使我只使用name = const_cast<char*>( n)(当我使用字符串而不是字符串Builder),但由于某种原因,不是从DLL回到C#。

我读到可能的原因是因为C 可以使用ASCII字符,而C#则使用16位字符,而解决的方法是包括CharSet = CharSet.Ansi,以便当它返回到C#时正确地编排了它,但是显然那个显然'Hash'Assn't帮助。

谁能告诉我我做错了什么?


解决方案
使用public ref class代替命名空间并使用void Foo( [Out] String^ %name)声明功能,以确保包括using namespace System::Runtime::InteropServices;

这告诉我您实际上有一个托管的C dll。

if( gp_app == nullptr)
    return false;

如果是这样,您可以导出托管类,并将字符串用作参数。

检查以下内容:http://msdn.microsoft.com/library/windows/apps/hh699870.aspx