指向非托管代码的int指针
本文关键字:int 指针 非托管代码 | 更新日期: 2023-09-27 18:09:10
我是c#新手,有一个简单的问题。从非托管代码中,我收到一个int指针:
public foo(ref IntPtr state)
{
_myState = state;
}
_myState
是该类的IntPtr
成员。现在我想通过_myState
与非托管c++代码交换状态。如果我这样写,一切正常:
public foo(ref IntPtr state)
{
_myState = state;
....do some stuff
state = 7;
}
在非托管应用程序中,我可以看到新值7
。但是如果我这样写:
public foo(ref IntPtr state)
{
_myState = state;
...do some stuff
_myState = 7;
}
则什么也没发生。state的初始值是0
,当将myState
更改为7
时,它在非托管应用程序中不会更新。我怎么能分配一个成员变量像_myState
的状态参数作为一个"指针",所以当状态更新,_myState
也更新?在c++中,这对于指针来说是没有问题的…
好的,下面是实际代码:
[DllExport("QFX_InitializeInterfaceObject", CallingConvention = CallingConvention.StdCall)]
public static void QFX_InitializeInterfaceObject(
long windowHandle,
ref IntPtr processState)
{
ChartWindowHandle = (IntPtr)windowHandle;
OrderCommandProcessState = processState;
}
我想要的是OrderCommandProcessState
得到与processState
相同的引用到它的值
首先,我要确保这一点是清楚的:IntPtr只是一个整数,恰好与该机器体系结构上的本机指针大小相同——例如,它是x64系统上的64位整数。它不一定具有指针的语义,尽管互操作代码将指针塞进IntPtrs中作为安全编组它们的一种方式是常见的。
继续你的具体问题,让我们忽略它是IntPtr这一事实。假设它只是一个int型,因为它基本上就是int型:
public void Foo(ref int x) // x is an alias to another variable of type int.
{
int y = x; // y is a copy of the contents of x
y = 7; // The contents of y are no longer a copy of the contents of x
}
改变y不会改变x;X是另一个变量的别名,y只是该变量内容的副本。它不是同一变量的别名。
如何使一个变量成为另一个变量的别名,以便当一个变量的状态更新时,链接的变量也被更新?在c++中,这对于指针来说是没有问题的。
今天在安全子集中,您只能通过方法的"ref"answers"out"参数来这样做。"ref"形参成为给定变量的别名。这是唯一安全的方法,你可以直接把一个变量作为另一个变量的别名。
CLR也支持ref locals。我们可以实现这样一个功能,事实上我已经用c#创建了原型。在我的原型中,你可以说:
public void Foo(ref int x) // x is an alias to another variable of type int.
{
ref int y = ref x; // y is now an alias to the same variable that x aliases!
y = 7; // changing y now changes x, and whatever x
// aliases, because those are all the same variable
}
但是我们还没有在c#中添加这个特性,而且近期也没有这样做的计划。如果你有一个令人信服的使用案例,我很乐意听到。(更新:该特性已添加到c# 7中。)
(CLR也允许"ref"返回类型。但是,CLR不允许为变量创建别名,然后将别名存储在字段中!字段的生命周期可能比链接变量的生命周期长,CLR设计者希望避免C和c++所面临的这类bug。
如果你知道变量被固定在内存中的特定位置,那么你可以关闭安全系统并创建一个指向该变量的指针;然后你就有了一个非常普通的指针,你可以像在c++中那样使用它。(也就是说,如果指针ptr
指向一个变量,那么*ptr
就是该变量的别名。)
unsafe public void Foo(int* x) // *x is an alias to a variable of type int.
{
int* y = x; // *y is now an alias to the same variable that *x aliases
*y = 7; // changing *y now changes *x, and whatever *x
// aliases, because those are all the same variable
}
CLR对指针的使用没有限制;如果需要,您可以自由地将它们存储在字段中。然而,如果您关闭安全系统,那么您负责确保垃圾收集器(或任何拥有该存储的内存管理器——它可能不是托管内存)在指针的生命周期内不会更改别名变量的位置。不要关闭安全系统,除非你真的知道你在做什么;那个安全系统是用来保护你的。