C#调用C ++ DLL函数返回一个结构 [英] C# Calling C++ DLL Function which returns a struct

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

问题描述

我有一个C ++ dll,它定义了一个结构体和一个dll调用:

I have an C++ dll which defines a struct and an dll call like this:

typedef const char* FString;

typedef struct {
    FString version;
    FString build_no;
    FString build_type;
    FString build_date;
    FString build_info;
    FString comment;
} FVersionInfo;

extern "C" FAPI_EXPORT FVersionInfo CALLINGCONV fGetVersion(void);

在c#端,我使用动态加载:

On the c# side i using an dynamic loading:

    [DllImport("kernel32.dll", EntryPoint = "LoadLibrary")]
    static extern int LoadLibrary(
        [MarshalAs(UnmanagedType.LPStr)] string lpLibFileName);

    [DllImport("kernel32.dll", EntryPoint = "GetProcAddress")]
    static extern IntPtr GetProcAddress(int hModule,
        [MarshalAs(UnmanagedType.LPStr)] string lpProcName);

    [DllImport("kernel32.dll", EntryPoint = "FreeLibrary")]
    static extern bool FreeLibrary(int hModule);

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public struct FVersionInfo
    {
        public string Version;
        public string Build_No;
        public string Build_Type;
        public string Build_Date;
        public string Build_Info;
        public string Comment;
    }

    [UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Ansi)]
    public delegate FVersionInfo fGetVersion();

    public fGetVersion GetVersion;

    FHandle = LoadLibrary(@pName);
    IntPtr intPtr;
    intPtr = GetProcAddress(FHandle, "fGetVersion");
    GetVersion = (fGetVersion)Marshal.GetDelegateForFunctionPointer(intPtr, typeof(fGetVersion));

调用代码应为:

FVersionInfo version = new FVersionInfo();
version = GetVersion();

我的第一个问题是,我在通话中成为 System.Runtime.InteropServices.MarshalDirectiveException c#加载部分中的Marshal.GetDelegateForFunctionPointer的代码。

My first problem is, that i become an "System.Runtime.InteropServices.MarshalDirectiveException" on the call of Marshal.GetDelegateForFunctionPointer in the c# loading part.

然后我使用IntPtr作为结构返回参数进行了测试,例如:

I have then tested using IntPtr as struct return parameter like that:

[UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Ansi)]
public delegate IntPtr fGetVersion();

所以我得到了Marshal.GetDelegateForFunctionPointer的支持,但是后来我遇到了与封送处理相同的问题:

So i got the Marshal.GetDelegateForFunctionPointer to work, but later i've got the same problems with marshaling:

IntPtr DllValue = new IntPtr();
FVersionInfo version = new FVersionInfo();
DllValue = fGetVersion();
Marshal.PtrToStructure(DllValue, FVersionInfo);

在这里,它在使用托管调试助手‘PInvokeStackImbalance’的fGetVersion()调用时崩溃。我认为这意味着堆栈已损坏(不平衡)。

Here it crashes at the fGetVersion() call with "Managed Debugging Assistant 'PInvokeStackImbalance'". I think it means, that the stack is corrupted (imbalanced).

我已经测试了结构定义的许多变体,但没有结果。

I have tested with many variants of the structure definition, but no result.

任何想法或建议都会受到欢迎!

Any ideas or suggestions would be welcome!

推荐答案

感谢方向,但我发现了一个可行的解决方案:

Thanks for the direction, but i found an working solution:


  1. 我将结构的声明更改为




[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct FVersionInfo
{
    public IntPtr Version;
    public IntPtr Build_No;
    public IntPtr Build_Type;
    public IntPtr Build_Date;
    public IntPtr Build_Info;
    public IntPtr Comment;
}





  1. 所以我顺利通过了 Marshal.GetDelegateForFunctionPointer

I将我的使用代码更改为:

I changed my using code to:




GF.FVersionInfo vi = new GF.FVersionInfo();
vi = gf.GetVersion();





  1. 之后那,我可以使用例如




string MyVersion = Marshal.PtrToStringAnsi(VersionInfos.Version );

string MyVersion = Marshal.PtrToStringAnsi(VersionInfos.Version);

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

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