导入C 功能将结构的指针返回到VB.NET中

Import C++ function returning pointer of structs into VB.NET

本文关键字:返回 VB NET 指针 功能 结构 导入      更新时间:2023-10-16

我已经在C 中创建了一个简单的DLL,其唯一目的是隔离问题并在小规模上测试,导入一个函数,该函数返回与不同类型成员的结构列表。

dll_header.h

#ifdef MY_DLL_EXPORTS
#define MY_DLL_API __declspec(dllexport)
#else
#define MY_DLL_API __declspec(dllimport)
#endif
enum color_type
{
    RGB = 1,
    MONO = 2
};
struct my_struct
{
    unsigned char *name;
    char *value;
    color_type type;
    my_struct* next;
};
extern "C" struct my_struct MY_DLL_API * get_list(void);

dll_header.cpp

#include "dll_header.h"
MY_DLL_API my_struct * get_list(void)
{
    my_struct my_list[2];
    unsigned char name1[] = "name1";
    unsigned char name2[] = "name2";
    char val1[] = "val1";
    char val2[] = "val2";
    my_list[0].name = name1;
    my_list[0].value = val1;
    my_list[0].type = RGB;
    my_list[0].next = &my_list[1];
    my_list[0].name = name2;
    my_list[0].value  = val2;
    my_list[0].type = MONO;
    my_list[0].next = NULL;
    return my_list;
}

就像我说的那样,我必须使用这些数据类型(不能将它们更改为字符串或其他任何东西,因为我正在测试某些东西,并且需要这样的东西)

现在,在我的vb.net应用程序中,我导入并尝试从dll

检索这样的列表

form1.vb

Imports System.Runtime.InteropServices
Imports System.Text
Public Class Form1
    Public Enum color_type
        RGB = 1
        COLOR = 2
    End Enum
    Private Structure my_struct
        Public name As Byte()
        Public value As Char()
        Public type As color_type
        Public next As IntPtr
    End Structure
    Private Declare Function get_list Lib "my_lib.dll" () As IntPtr
    Private my_list As List(Of my_struct)
    Private Sub get_list()
        Dim my_list_pointer As IntPtr = get_list()
        my_list = New List(Of my_struct)
        Dim my_item As my_struct
        While my_list_pointer <> IntPtr.Zero
            my_item = CType(Marshal.PtrToStructure(my_list_pointer, GetType(my_struct)), my_struct)
            my_list.Add(my_item)
            my_list_pointer = my_item.next
        End While
    End Sub

我尝试了许多其他方法,这些方法特殊更改了数据类型,但是到目前为止,我在尝试运行代码时坚持使用此例外:

system.AccessviolationException:'试图读取或写下受保护的 记忆。这通常表明其他记忆是损坏的。'

试图找到一种使这两个人相互理解的方法

要么使用混合模式C 在本机和托管类型之间进行翻译,要么使用与p/indoke兼容的类型。

查看Win32如何定义结构(以及使用这些功能)是一个良好的开始,可以帮助您了解如何将兼容结构定义为P/Invoke的主要目的之一,即能够使用托管代码中的Win32 API。

如果您选择混合模式,则可以在世界两者之间进行任何必要的翻译,因为您可以在同一组件中混合本机C 和C /CLI。因此,从本质上讲,您将编写将本机结构转换为托管结构的代码,然后VB.NET可以使用该托管代码(假设您使用vb.net中可用的类型)。

好吧,如果您选择混合模式路线,则通常会以3个dll/zhoundberies/operutable最终结束,因为您将拥有原始的C DLL(本机代码),VB.NET代码(托管)和混合模式C 组装之间。

update

虽然仅读取列表,但如果不是这种情况,则相对容易提供代码,但根据预期的代码的使用以及现有DLL中的可用函数,可能会更难。

起点是在C /CLI中创建ref class

一些类似的问题

https://bytes.com/topic/c-sharp/answers/674468-passing-link-list-list-c-dll-c-pinvoke

使用PINVOKE

从C到C#的点(X,Y,Z)的返回列表

从C

的自我参考结构的Pinvoke

您的代码问题

您的导出函数重新调整指向不确定行为的本地变量的指针。

附加观察

如果您的原始列表是一个数组,为什么还将其列入列表?阵列更容易元帅和使用。而且表现也更好。

定义结构时,您已经明确说明字符串的编组方式以及应使用的对齐方式。您将验证一切都是预期的。