【问题标题】:F# Dynamic Eval, Reflection, ILF# 动态评估、反射、IL
【发布时间】:2012-11-21 08:05:50
【问题描述】:

由于我似乎将 95% 的编码时间都花在了 F# 的 FSI 上,所以我绕道(参见:Distracted)并想编写一些实用函数。

我感兴趣的特定实用程序是一个“反汇编”(http://www.cons.org/cmucl/doc/reading-disassembly.html) 函数,它可以为给定函数转储 IL,稍后可能计数指令,基本静态分析等,通常这只是分散注意力的天堂。我已经编写了将 byteArrayIL 映射到 MSIL 名称的代码(几乎)。

这里是用来从当前模块获取函数名的sn-p:

let dec_c = MethodBase.GetCurrentMethod().DeclaringType

System.Reflection.Assembly.GetAssembly(dec_c).GetTypes() 
|> Seq.map (fun x -> x.FullName) //, get_function_instructions x)

这几乎可以正常工作,因为 x.FullName 反映了实际的函数名称:

FSI_0001
<StartupCode$FSI_0001>.$FSI_0001
FSI_0002
FSI_0002+instructions_of_bytes@24
FSI_0002+remove_null_function_body_bytes@32
FSI_0002+remove_null_function_body_bytes@31-1
FSI_0002+resolve_IL_from_bytes@38
FSI_0002+resolve_IL_from_bytes@36-1
FSI_0002+it@49
FSI_0002+it@50-1
<StartupCode$FSI_0002>.$FSI_0002
FSI_0003
FSI_0003+it@49-2
FSI_0003+it@50-3
<StartupCode$FSI_0003>.$FSI_0003

所以我们可以很容易地编写一个函数来根据我们的函数名进行过滤。

不幸的是(可能是由于我的误解),似乎并非所有函数都以这种方式可用,例如如果我们定义以下简单函数然后重新运行转储:

(* reload FSI *)
let simple_add x = x + 1
(* rerun the function name dumping *)

FSI_0001
<StartupCode$FSI_0001>.$FSI_0001
FSI_0002
FSI_0002+instructions_of_bytes@24
FSI_0002+remove_null_function_body_bytes@32
FSI_0002+remove_null_function_body_bytes@31-1
FSI_0002+resolve_IL_from_bytes@38
FSI_0002+resolve_IL_from_bytes@36-1
FSI_0002+it@50
FSI_0002+it@51-1
<StartupCode$FSI_0002>.$FSI_0002

奇怪的是,结果文本中不存在“simple_add”函数。

想法: 1. 可能simple_add这个函数没有通过反射实现,直到看到被使用?听起来很奇怪。 2. 可能是那些“FSI_0002+it”字符串之一实际上是我们的函数。

问题: 1. 为什么输出没有反映所有的函数名? 2. 有没有更好的方法?

【问题讨论】:

  • &lt;StartupCode$FSI_0001&gt;.$FSI_0001 似乎是simple_add
  • 我猜这可能是因为您可以定义两次值,因此使用基于模拟行的名称而不是真实名称,并且 FSI 有一个从标签到最新模拟名称的表。
  • 啊.. 有道理,但是如果您有 2 个要检查的函数,或者 15、100000 等,将很难猜测它可能是哪个函数,
  • 我不认为 FSI 真的是为调试和动态操作而设计的 :) 我知道 FSC 会生成合理的名称(即使 lambdas 有其父函数的名称,除了它们的行号和唯一的标识符)。
  • 你可能是对的,但它会是一个很酷的功能!

标签: reflection f# cil


【解决方案1】:

我想我已经睡了(半睡)答案,我做错了,没有必要列出每个函数的字符串名称...

let get_function_instructions (mb : System.Type) = 
  mb.GetMethods() 
  |> Seq.map ...

let find_func_print_instructions f =
  f.GetType()
  |> get_function_instructions 
  |> print_instruction_text

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-07-23
    • 2017-10-14
    • 2016-08-25
    • 1970-01-01
    • 2021-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多