如何在VB.NET中获取指向整数的IntPtr?

4
我需要获取一个整数的地址,并将其分配给IntPtr以在API中使用。怎么做?
Dim my_integer as Integer
Dim ptr as new IntPtr

' This fails because AddressOf can only be used for functions.
ptr = AddressOf my_integer

APICall(ptr)

我该怎么做?


.NET让使用指针变得复杂 - 有很好的理由。为什么需要一个指向int的指针? - Tobias Langner
1
正如我之前所提到的,对于一个API调用,它将修改整数的值。 - andrewrk
4个回答

3
简短回答:你不能这样做,也不需要这样做。(虽然在C#中有一种方法可以实现。)
但是还有其他方法可以做到这一点。当你声明外部函数APICall时,你需要声明它的参数为ByRef,并直接使用它。CLR会负责获取地址。
我是一个C#程序员,不记得VB.NET的语法,所以请原谅。以下是C#中APICall的声明和使用。在VB.NET中需要类似的操作。
[DllImport("FooBar.dll")]
static extern APICall(ref int param);

int x = 3;
APICall(ref x);

总之,无论是C#还是VB.NET,关键在于如何声明APICall,而不是获取整数的地址。

这个问题在于,API是这样编写的,以便这个特定的函数可以发送任何东西。它使用了一个void指针。必须保持这种方式,否则我无法将该函数用于任何其他类型的访问。EdsError EDSAPI EdsGetPropertyData( EdsBaseRef inRef, EdsPropertyID inPropertyID, EdsInt32 inParam, EdsUInt32 inPropertySize, EdsVoid *outPropertyData )请注意最后一个参数。根据inPropertyID,outPropertyData可能指向任何内容。在我的情况下,它是一个整数。 - andrewrk
+1. 我建议你将你的简短回答改为“你不需要那个”。在C#和VB.NET中,正确导入非托管函数是正确的方法。 - okutane
Dmitriy:好建议。已完成。 - Gregory Higley
@superjoe30:你将需要为每种想要传递的类型创建重载。据我所知,在C#或VB.NET中没有void *的等效项。 - Gregory Higley
@superjoe30:实际上,你不能这样说:在VB.NET中,你不能直接获取整数的地址。虽然Marshal可能有效,但它并不是直接等效的,而且我也不建议这样做。 - Gregory Higley
显示剩余6条评论

3

您可能需要使用Marshal类。 这篇文章(现在可能有点过时)提供了一些很好的例子。

然而,我建议先阅读Gregory的其他答案,其中讲述了声明外部函数并尝试以那种方式完成。 使用Marshal应该是最后的选择。


2
Imports System.Runtime.InteropServices

Dim my_integer as Integer = 0
Dim ptr as IntPtr = Marshal.AllocHGlobal(4)

Marshal.WriteInt32(my_integer)

APICall(ptr)

my_integer = Marshal.ReadInt32(ptr)

Marshal.FreeHGlobal(ptr)

1
不要忘记使用 AllocHGlobal 分配的内存需要释放。 - Gregory Higley
1
@superjoe30,你是不是通过我提供的链接才意识到这一点的?还是有什么魔法让你突然就明白了? - Ash
1
Ash,我已经点赞了你的回答,然后找到了我的问题的实际源代码答案并发布了它,我认为这为页面提供了价值。 - andrewrk
1
你应该把 Marshal.WriteInt32(my_integer) 改成 *Marshal.WriteInt32(ptr, my_integer)*。 - γηράσκω δ' αεί πολλά διδασκόμε

0

我可能完全错了,但你试过这个吗?

Dim MyInt32 As Integer = 0
Dim MyPtr As IntPtr = MyInt32

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接