ihtiyaç MethodInfo ve örnek Tipi sahip verilmiş OpCodes.Callvirt ile OpCodes.Constrained dışarı verir Nasıl il : ILGenerator
işlevine geneldir ve exp
tip-kontrol çözümlü dili temsil eden bir ayırt edici birliktir emit : Map<string,LocalBuilder> -> exp -> unit
dava ile InstanceCall of exp * MethodInfo * exp list * Type
ve Type
ifade Tipi temsil exp
bir özelliktir.Ben özyinelemeli fonksiyonu var yandan
Aşağıdaki parçada, instance.Type
'un bir ValueType
olabilir veya olmayabilir bir örnek çağrı için IL opcodes yayımlamaya çalışıyorum. Bu yüzden, referans, değer ve enum türlerinde sanal aramaları esnek ve verimli bir şekilde yapmak için OpCodes.Constrained
'u kullanabileceğimi anlıyorum. Reflection.Emit ve makine dilleri için yeni biriyim, bu yüzden OpCodes.Constrained
için bağlantılı belgeleri anlamak benim için güçlü değil.
İşte benim girişimi, ama bir VerificationException
sonuçlanır "Operasyon Çalışma zamanını bozabilir.":
let rec emit lenv ast =
match ast with
...
| InstanceCall(instance,methodInfo,args,_) ->
instance::args |> List.iter (emit lenv)
il.Emit(OpCodes.Constrained, instance.Type)
il.Emit(OpCodes.Callvirt, methodInfo)
...
docs bakınca anahtar olabilir düşünüyorum "A, işaretçi, ptr yönetilen yığını üzerine itilir. ptr türü thisType bir yönetilen işaretçi (&) olması gerekir. Bu thisType bir referans beklediği bir öneksiz callvirt talimat durumunda, farklı olduğuna dikkat edin."
Güncelleme size @Tomas ederiz ve OpCodes.Constrained
ne zaman kullanılacağına @desco, şimdi (instance.Type
bir ValueType olmakla methodInfo.DeclaringType
bir referans türüdür) anlıyoruz.
Ama şu anda bu davayı ele almam gerekmiyor ve benim asıl problemim yığındaki örnek argümanıydı: sadece değer yerine bir adrese ihtiyacı olduğunu öğrenmek için 6 saatimi aldı DLR kaynak kodunda bana ipuçları verdi ve sonra basit bir C# programında ilasm.exe kullanarak temizleyin). Sana soru sonunda aktardığı belgelerin bit sorunun kaynağı olduğunu düşünüyorum
let rec emit lenv ast =
match ast with
| Int32(x,_) ->
il.Emit(OpCodes.Ldc_I4, x)
...
| InstanceCall(instance,methodInfo,args,_) ->
emit lenv instance
//if value type, pop, put in field, then load the field address
if instance.Type.IsValueType then
let loc = il.DeclareLocal(instance.Type)
il.Emit(OpCodes.Stloc, loc)
il.Emit(OpCodes.Ldloca, loc)
for arg in args do emit lenv arg
if instance.Type.IsValueType then
il.Emit(OpCodes.Call, methodInfo)
else
il.Emit(OpCodes.Callvirt, methodInfo)
...