VB.net 将结构传递给非托管 dll

问题描述:

我正在将一些 VB6 代码迁移到 VB.net,该代码包含一个包含一维数组、二维数组和一些其他变量的结构.

I'm migrating some VB6 code to VB.net, the code contains a structure that contains 1d arrays, 2d arrays, and few other variables.

Vb.net 结构的大纲如下

The general outline of the Vb.net structure is as under

Public Structure Test

    Dim a As Single
    Dim b As Single
    Dim c As Single
    <VBFixedArray(2)> Dim arr1() As Single
    <VBFixedArray(2, 2)> Dim mdarr1(,) As Single
    <VBFixedArray(4)> Dim arr2() As Byte
    <VBFixedArray(4)> Dim arr3() As Short
    <VBFixedArray(3, 2)> Dim mdarr2(,) As Integer

    Dim d As Integer
    Dim e As Decimal

End Structure

对dll的调用声明如下

The call to the dll is declared as under

Public Declare Sub getState Lib "val.dll" (ByRef state As Test)

在此站点的其他地方,我意识到我们必须编组"结构以使其与即将接受它的非托管代码兼容.

Elsewhere on this site I realized that we have to "marshal" the structure to allow it to be compatible with the unmanaged code that is about to accept it.

但是,我在运行代码时仍然收到运行时错误,我不知道如何使用 System.Runtime.InteropServices.Marshal 类.

However I still receiving runtime errors when running the code, I don't have any clue of how to use the System.Runtime.InteropServices.Marshal class.

将此结构传递给 dll 的正确方法是什么?

What would be the correct way to pass this structure to the dll?

原来的VB6数据类型是

The original VB6 data type is

Public Type Test

    a As Single
    b As Single
    c As Single
    arr1(0 To 2) As Single
    mdarr1(0 To 2, 0 To 2) As Single
    arr2(0 To 4) As Byte
    arr3(0 To 4) As Integer
    mdarr2(0 To 3, 0 To 2) As Long

    d As Long
    e As Currency

End Type

val.dll 中是否有 getState 的源代码?如果它是用 C 或 C++ 编写的,并且您有源代码甚至只是标题,则可以使用 P/Invoke Assistant 自动生成您的 VB.Net 代码.

Do you have the source code for getState in the val.dll? If it's written in C or C++, and you have the source code or even just the headers, you could use the P/Invoke Assistant to automatically generate your VB.Net code.

或者...(并且请发布原始的 VB6 结构!)

Alternatively... (and please do post the original VB6 structure!)

  • 您可能需要在调用 getState 之前分配数组,例如state.arr1 = {0.0, 0.0}
  • Decimal 变量 e 可能会给您带来问题.在 VB6 中,这可能是一个 Currency 变量,据我所知,Decimal 并不是完全等效的.将有一种方法可以告诉 VB.Net 像货币一样编组它.也许添加一个 属性 像这样......
  • You might need to allocate the arrays before calling getState, e.g. state.arr1 = {0.0, 0.0} etc.
  • The Decimal variable e could cause you a problem. In VB6 this was probably a Currency variable, and Decimal is not an exact equivalent as far as I can remember. There will be a way to tell VB.Net to marshal it like a Currency. Perhaps adding an attribute like this...

示例代码:

 Imports System.Runtime  
 Public Structure Test  
   ''blah blah

   <InteropServices.MarshalAs(InteropServices.UnmanagedType.Currency)> _  
   Dim e As Decimal  

   ''blah blah