gpt4 book ai didi

c++ - VB.net 2010 中 GCC 编译的 c++ dll 的 Pinvoke 问题

转载 作者:行者123 更新时间:2023-11-28 06:21:34 25 4
gpt4 key购买 nike

好吧,我试着自己解决这个问题。这是我遇到的问题:

为了让该函数在 dll 中运行,我必须在我的 vb 代码中发送一个指向结构的指针,因为我需要用文件中的数据填充该结构,反之亦然。将函数编译为 dll 更容易,然后尝试在 vb 中重写 native C 函数,我从未像 memmove() 这样使用过。

Dll 文件有效,因为我还编写了一个 c++ 应用程序,它从 dll 调用函数,从指针填充内存中的结构,然后在命令提示符中显示数据。我只需要弄清楚事物的视觉基本方面有什么问题。

导出函数的 C++ 头信息

#define MAX_CHEATS 150
struct SCheat
{
uint32_t address;
uint8_t byte1;
uint8_t saved_byte;
bool enabled;
bool saved;
char name[22];
};
struct SCheatData
{
struct SCheat c[MAX_CHEATS];
uint32_t num_cheats;
};
__declspec(dllexport) int __cdecl S9xLoadCheatFile (const char *, struct SCheatData *Cheat);
__declspec(dllexport) int __cdecl S9xSaveCheatFile (const char *, struct ScheatData *Cheat);

我写了一个 c++ 应用程序来测试 dll 功能,它运行完美。

我还应该提到在 github 上找到了原始版本的 c++ 代码。我只需要为 Snes9x 加载/保存 cht 文件的功能。如果我能解决这个问题,我就可以轻松添加其余的模拟器作弊文件结构和加载/保存功能,我的应用程序将为任何模拟器生成 cht 文件,同时将所有作弊文件保存在中央数据库中。

现在我们开始讨论 vb 部分。

以下是我在应用中定义的结构和调用。

<StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)> _
Public Structure SCheat
<MarshalAs(UnmanagedType.U4)> Public address As UInteger
<MarshalAs(UnmanagedType.U4)> Public byte1 As Byte
<MarshalAs(UnmanagedType.U4)> Public saved_byte As Byte
<MarshalAs(UnmanagedType.U4)> Public enabled As Integer
<MarshalAs(UnmanagedType.U4)> Public saved As Integer
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=22)> Public name() As Char
End Structure
<StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)> _
Public Structure SCheatData
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=150)> Public Shared c() As SCheat = Arrays.InitializeWithDefaultInstances(Of SCheat)(150)
<MarshalAs(UnmanagedType.U4)> Public num_cheats As UInteger
End Structure

这是我定义函数的方式。

<DllImport("c:\minGW\bin\Cheat_Functions.dll", CallingConvention:=CallingConvention.Cdecl)> _
Public Function _Z16S9xLoadCheatFilePKcP10SCheatData(ByVal filename As String, ByVal cheat As IntPtr) As Integer
End Function

Declare Function S9xLoadCheatFile Lib "c:\minGW\bin\Cheat_Functions.dll" Alias "_Z16S9xLoadCheatFilePKcP10SCheatData" (ByVal filename As String, ByRef cheat As IntPtr) As Integer


Declare Function S9xSaveCheatFile Lib "c:\minGW\bin\Cheat_Functions.dll" Alias "_Z16S9xSaveCheatFilePKcP10SCheatData" (ByVal filename As String, ByRef cheat As SCheatData) As Integer

我曾尝试通过 ref 传递结构,但它崩溃了,并显示了一条关于读/写 protected 内存的非描述性消息。我尝试编码(marshal) structuretoptr 的一个变量,它变得更远了一点,但破坏了应用程序中的所有内存。我认为这是一个没有完全理解 pinvoke 和编码实际上是如何工作的问题,或者我的结构可能与 dll 正在寻找的不匹配。

如有任何帮助,我们将不胜感激。

最佳答案

编辑:抱歉,但我忘记了您的目标是 VB,尽管将我的代码翻译成它应该没有太大问题:D

以下对我有用:

using System;
using System.Runtime.InteropServices;
using System.Windows;

namespace WpfApplication3
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var intPtr = GetData();
var ptrToStructure = Marshal.PtrToStructure<SCheatData>(intPtr);
}

[DllImport("mydll.dll")]
private static extern IntPtr GetData();

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct SCheat
{
public uint address;
public byte byte1;
public byte saved_byte;
[MarshalAs(UnmanagedType.I1)] public bool enabled;
[MarshalAs(UnmanagedType.I1)] public bool saved;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 22)] public string name;
}

[StructLayout(LayoutKind.Sequential)]
public struct SCheatData
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 150, ArraySubType = UnmanagedType.Struct)] public SCheat[]
c;

public uint num_cheats;
}
}
}

和:

// mydll.cpp : Defines the exported functions for the DLL application.
//

#include "stdafx.h"
typedef unsigned char uint8_t;
typedef unsigned int uint32_t;
#define MAX_CHEATS 150

struct SCheat
{
uint32_t address;
uint8_t byte1;
uint8_t saved_byte;
bool enabled;
bool saved;
char name[22];
};

struct SCheatData
{
struct SCheat c[MAX_CHEATS];
uint32_t num_cheats;
};

extern "C" __declspec(dllexport) SCheatData* GetData()
{
SCheatData* data = new SCheatData();
data->num_cheats = MAX_CHEATS;
for (size_t i = 0; i < MAX_CHEATS; i++)
{
SCheat c;
c.address = 1234;
c.byte1 = 0xAB;
c.saved_byte = 0xCD;
c.enabled = true;
c.saved = true;
strcpy(c.name, "abcdefghijklmnopqrstu");
data->c[i] = c;
}
return data;
}

我用过PInvoke Interop Assistant这对于生成签名非常有帮助,还要注意 Marshal.PtrToStructure 的不同重载,因为并非所有风格都适用于任何情况。

关于c++ - VB.net 2010 中 GCC 编译的 c++ dll 的 Pinvoke 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29221946/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com