- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在处理 ILGenerator
使用 Expression
帮助发射 IL 片段的扩展.一切都很好,直到我处理整数转换部分。有些东西对我来说确实违反直觉,例如:
conv.i8
转换 Int32
至 UInt64
conv.u8
转换 UInt32
至 Int64
IntPtr
的转换.它必须更棘手,因为它的长度是可变的。我决定看看 C# 编译器是如何实现它的。
IntPtr
至
Int64
转换。显然,所需的行为应该是:在 64 位系统上无操作,或在 32 位系统上进行符号扩展。
native int
由
IntPtr
包裹struct,我得看看它的主体
Int64 op_Explicit(IntPtr)
方法。以下是 dnSpy 从 .NET core 3.1.1 反汇编的:
.method public hidebysig specialname static
int64 op_Explicit (
native int 'value'
) cil managed
{
.custom instance void System.Runtime.CompilerServices.IntrinsicAttribute::.ctor() = (
01 00 00 00
)
.custom instance void System.Runtime.Versioning.NonVersionableAttribute::.ctor() = (
01 00 00 00
)
.maxstack 8
IL_0000: ldarga.s 'value'
IL_0002: ldfld void* System.IntPtr::_value
IL_0007: conv.u8
IL_0008: ret
}
conv.u8
出现在这里!它将在 32 位系统上执行零扩展。我用以下代码确认了这一点:
delegate long ConvPtrToInt64(void* ptr);
var f = ILAsm<ConvPtrToInt64>(
Ldarg, 0,
Conv_U8,
Ret
);
Console.WriteLine(f((void*)(-1))); // print 4294967295 on x86
static long Convert(IntPtr intp) => (long)intp;
;from SharpLab
C.Convert(IntPtr)
L0000: mov eax, ecx
L0002: cdq
L0003: ret
Int64 op_Explicit(IntPtr)
有一个
Intrinsic
属性。是不是方法体被运行时 JIT 完全忽略了,而是被一些内部实现取代了?
IntPtr
的转换方法吗?实现我的转换?
ILAsm
执行:
static T ILAsm<T>(params object[] insts) where T : Delegate =>
ILAsm<T>(Array.Empty<(Type, string)>(), insts);
static T ILAsm<T>((Type type, string name)[] locals, params object[] insts) where T : Delegate
{
var delegateType = typeof(T);
var mi = delegateType.GetMethod("Invoke");
Type[] paramTypes = mi.GetParameters().Select(p => p.ParameterType).ToArray();
Type returnType = mi.ReturnType;
var dm = new DynamicMethod("", returnType, paramTypes);
var ilg = dm.GetILGenerator();
var localDict = locals.Select(tup => (name: tup.name, local: ilg.DeclareLocal(tup.type)))
.ToDictionary(tup => tup.name, tup => tup.local);
var labelDict = new Dictionary<string, Label>();
Label GetLabel(string name)
{
if (!labelDict.TryGetValue(name, out var label))
{
label = ilg.DefineLabel();
labelDict.Add(name, label);
}
return label;
}
for (int i = 0; i < insts.Length; ++i)
{
if (insts[i] is OpCode op)
{
if (op.OperandType == InlineNone)
{
ilg.Emit(op);
continue;
}
var operand = insts[++i];
if (op.OperandType == InlineBrTarget || op.OperandType == ShortInlineBrTarget)
ilg.Emit(op, GetLabel((string)operand));
else if (operand is string && (op.OperandType == InlineVar || op.OperandType == ShortInlineVar))
ilg.Emit(op, localDict[(string)operand]);
else
ilg.Emit(op, (dynamic)operand);
}
else if (insts[i] is string labelName)
ilg.MarkLabel(GetLabel(labelName));
else
throw new ArgumentException();
}
return (T)dm.CreateDelegate(delegateType);
}
最佳答案
我犯了一个错误。 Int64 op_Explicit(IntPtr)
有两个版本。
64位版本位于“C:\Program Files\dotnet...”,其实现为:
.method public hidebysig specialname static
int64 op_Explicit (
native int 'value'
) cil managed
{
.maxstack 8
IL_0000: ldarga.s 'value'
IL_0002: ldfld void* System.IntPtr::_value
IL_0007: conv.u8
IL_0008: ret
}
.method public hidebysig specialname static
int64 op_Explicit (
native int 'value'
) cil managed
{
.maxstack 8
IL_0000: ldarga.s 'value'
IL_0002: ldfld void* System.IntPtr::_value
IL_0007: conv.i4
IL_0008: conv.i8
IL_0009: ret
}
conv.i8
将在这里完成工作。
IntPtr
的任务。转换,因为在运行时,'IntPtr' 的长度是已知的(据我所知是 32 或 64),并且大多数发出的方法不会被保存和重用。但我仍然想要一个独立于运行时的解决方案,我想我已经找到了。
关于c# - 将 IntPtr 转换为 Int64 : conv. u8 或 conv.i8?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60881564/
我正在尝试使用 BitmapData 类?并且在将 IntPtr 值分配给 BitmapData.Scan0 属性时遇到一些问题。这是我的代码: var data = bmp.LockBits(new
我正在尝试使用 BitmapData 类?并且在将 IntPtr 值分配给 BitmapData.Scan0 属性时遇到一些问题。这是我的代码: var data = bmp.LockBits(new
我有两个 IntPtr 值指向一些 length 字节的数据区域。 length 可能有 200k 到 400k 的数量级。 int length = /* ..*/ IntPtr ptrSrc =
我在网上到处都看过,似乎找不到能够解决该问题的特定答案。从字面上看,这是我得到的唯一错误,只有在解决此问题后才能构建可执行文件。 int num3 = new VAMemory(Data.proces
我不知道 Copy(IntPtr[], Int32, IntPtr, Int32) 方法是如何工作的。我虽然它可以将多个 IntPtr 中包含的数据复制到一个 IntPtr 中(如 MSDN 所述),
我有一个类的以下代码。这是一个类的初始化。 第三方动态链接库 [DllImport("gdi32.dll")] public static extern IntPtr CreateCompatib
我刚刚了解到 IntPtr.Zero 无法与 default(IntPtr) 相提并论。谁能告诉我为什么? IntPtr.Zero == new IntPtr(0) -> "could not eva
这两种说法有什么区别吗: IntPtr myPtr = new IntPtr(0); IntPtr myPtr2 = IntPtr.Zero; 我见过许多使用 PInvoke 的示例,如果 myPtr
这个问题已经有答案了: What makes more sense - char* string or char *string? [duplicate] (13 个回答) 已关闭 9 年前。 本能地
我知道 Marshal.SizeOf() 和 sizeof() 有多么根本的不同。但是在 IntPtr 的情况下,无论 CPU 架构如何,它们都不会总是返回完全相同的东西吗? 最佳答案 一方面,有原始
我需要实现一个与找到的解决方案非常相似的解决方案 here ,写于 2009 年,用于检索文件的唯一标识符。具体来说,我正在查看答案的 ApproachB()函数和以下行(重写了一点以反射(refle
是否可以通过 Skype 用户窗口获取处理程序并使用 SendMessage(whdl,BM_CLICK,intptr.zero,intrptr.zero,intptr.zero) 单击发送文件或调用
经过一些研究我翻译了 pHandle = IntPtr.Zero; 到德尔福 var pHandle: Pointer; 当我在 Delphi 中中断调试时,我得到 $314328,当我在 C s
运营商的description on MSDN有一句话: An exception is only thrown if the value of value requires more bits th
这个函数在一个循环中。当我运行程序时,带有 IntPtr 的行给我内存问题,我已经删除 [],但它仍然没有解决内存问题,有人可以帮忙吗?谢谢 void showImage(IplImage *img,
直到最近,我还认为在 P/Invoke 中编码 IntPtr 只会涉及“blitting”操作;即简单地从例如复制指针C++ 到 C#。 然而,我最近与某人交谈时提到,事情远不止于此。他特别提到 In
我目前正在编写一些代码,这些代码反射(reflect)了从对 native dll 的调用中编码返回的结构。一些结构包含指向以 null 结尾的指针数组的 IntPtr* 字段。这些字段需要特殊处理。
我正在尝试在 Ubuntu 14.04 上使用 Mono 执行函数 P/Invoke: [DllImport(@"libRT", CharSet = CharSet.Ansi, CallingConv
我有一个类定义如下: [StructLayout(LayoutKind.Sequential)] public class OUR_MEM_STR {
我遇到了一段C#源码如下 int* ptr = ...; int w = ...; int* ptr3 = ptr + (IntPtr)w; CS0019: Operator '+' cannot
我是一名优秀的程序员,十分优秀!