C#调用C ++ DLL函数返回一个结构

问题描述 投票:2回答:2

我有一个C ++ dll,它定义了一个结构和一个像这样的dll调用:

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#端,我使用动态加载:

    [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();

我的第一个问题是,在c#加载部分的Marshal.GetDelegateForFunctionPointer调用中,我变成了“ System.Runtime.InteropServices.MarshalDirectiveException”。

然后我使用IntPtr作为这样的结构返回参数进行了测试:

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

所以我让Marshal.GetDelegateForFunctionPointer正常工作,但后来我遇到了与封送处理相同的问题:

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

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

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

欢迎任何想法或建议!

c# c++ dll call
2个回答
1
投票

感谢方向,但我找到了可行的解决方案:

  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

  2. 我将使用代码更改为:

GF.FVersionInfo vi = new GF.FVersionInfo();
vi = gf.GetVersion();
  1. 之后,我可以使用以下方式访问字符串

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


0
投票

[抱歉,我想问一个问题。如果在dll c ++中:

typedef struct {
 WORD       num
} FVersionInfoChild
typedef struct {
    FString version;
   FVersionInfoChild arrayStruct[8];
} FVersionInfo

然后,在C#中如何获取Struct数组?

© www.soinside.com 2019 - 2024. All rights reserved.