C# と VB.NET の質問掲示板

わんくま同盟

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト


■91223 / )  Re[3]: VB.NETからC++のdll関数への参照渡しについて
□投稿者/ 魔界の仮面弁士 (2198回)-(2019/06/06(Thu) 15:20:06)
2019/06/07(Fri) 11:30:36 編集(投稿者)

※Console.WriteLine 時にスペルミスしていたので、コードを再整理

No91214 (まる さん) に返信
> VB6ではなぜ上手くいき

参照設定で配列を渡す場合は、SAFEARRAY や VARIANT で丸ごと受け渡していたので、
配列の先頭要素を参照渡しする方法は経験が無いのですよね…。

Declare な方では、先頭要素を参照渡しする方法も良く使っていたのですが。


> cpp,hpp,odlそれぞれに記載されたAAAの宣言を編集する必要がある、という事でしょうか…?

C++ 側は専門外なので、こっちは何とも。


>>> Dim objHandle As GCHandle = GCHandle.Alloc(shtArray(0),GCHandleType.Pinned)
>>> Dim intPinned As Intptr = objHandle.AddrOfPinnedObject()


intPinned をどうやって DLL に渡すのかが読み取れなかったのですが、
先頭要素だけを Pinned しても駄目だと思います。


Imports System.Runtime.InteropServices
Module Module1

  Sub Main()
    Dim bin As Byte() = {&H11, &H22, &H33, &H44, &H55, &H66, &H77, &H88, &H99, &HAA, &HBB, &HCC, &HDD, &HEE, &HFF}
    'Dim bin As Byte() = {&HFE, &HDC, &HBA, &H98, &H76, &H54, &H32, &H1F, &HED, &HCB, &HA9, &H87, &H65, &H43, &H21}

    Console.WriteLine("=== bin (サンプルデータ) ===")
    Dump(bin)

    ' bin よりも少し大きめに確保
    Dim ary1 As Short() = Enumerable.Repeat(&H1234S, 20).ToArray()
    Dim ary2 As Short() = Enumerable.Repeat(&H1234S, 20).ToArray()

    Console.WriteLine("=== Short 配列全体を Pinned した場合 ===")
    Dim h1 As GCHandle = GCHandle.Alloc(ary1, GCHandleType.Pinned)
    CopyMemory(bin, h1)
    h1.Free()

    Console.WriteLine("=== Short 配列の先頭要素だけを Pinned した場合 ===")
    Dim h2 As GCHandle = GCHandle.Alloc(ary2(0), GCHandleType.Pinned)
    CopyMemory(bin, h2)
    h2.Free()

    Console.WriteLine("=== ary1 は書き換わっている ===")
    Dump(ary1)

    Console.WriteLine("=== ary2 は書き換わらない ===")
    Dump(ary2)

    Console.ReadLine()
  End Sub

  Sub CopyMemory(source As Byte(), h As GCHandle)
    Dim t As Type = h.Target.GetType()
    Console.WriteLine("Target Is {0} / {1}", TypeName(h.Target), t.Name)
    Dim et As Type = If(t.IsArray(), t.GetElementType(), t)
    Dim sz As Integer = Marshal.SizeOf(et)
    Dim p As IntPtr = h.AddrOfPinnedObject()
    Console.WriteLine("p => 0x{0:X} (address)", p)

    Console.WriteLine("--- コピー前 ---", p)
    Console.WriteLine("p = 0x{0:X}", Marshal.ReadInt64(p))
    For n = 0 To 3
      Console.WriteLine("p[{0}] = 0x{1:X}", n, Marshal.PtrToStructure(IntPtr.Add(p, n * sz), et))
    Next

    Marshal.Copy(source, 0, p, source.Length)

    Console.WriteLine("--- コピー後 ---", p)
    Console.WriteLine("p = 0x{0:X}", Marshal.ReadInt64(p))
    For n = 0 To 3
      Console.WriteLine("p[{0}] = 0x{1:X}", n, Marshal.PtrToStructure(IntPtr.Add(p, n * sz), et))
    Next
  End Sub

  Sub Dump(Of T As Structure)(ary As T())
    Dim bytes As Integer = Marshal.SizeOf(Of T)()
    Console.Write(" Len={0}:", bytes * ary.Length)
    Dim fmt As String = " {0:X" & CStr(2 * bytes) & "}"
    For Each x As T In ary
      Console.Write(fmt, x)
    Next
    Console.WriteLine()
  End Sub
End Module
返信 編集キー/


管理者用

- Child Tree -