3

次のような構造体と dll 呼び出しを定義する C++ 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);

ここでは、「Managed Debugging Assistant 'PInvokeStackImbalance'」を使用した fGetVersion() 呼び出しでクラッシュします。スタックが壊れている(バランスが取れていない)ことを意味していると思います。

構造定義の多くのバリアントでテストしましたが、結果はありません。

どんなアイデアや提案も大歓迎です!

4

2 に答える 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);

于 2013-06-12T14:09:03.050 に答える