"Managed" (编译类型)
"Managed" (编译类型)
"Managed"::[t]
代表一个将自动内存管理添加到 t 的类型.
更多信息
- "Managed" 为类型添加内存管理,例如由外部库暴露的类型.
- t 不能是已拥有自动内存管理的状态.
- "Managed" 使用自动引用计数来自动释放不再使用的对象.
- 从编译代码返回的托管对象继续由 Wolfram Language 内核进行内存管理.
- 当作为参数传递给由 LibraryFunctionDeclaration 声明的函数时,托管对象会自动解包. »
函数构造
- CreateTypeInstance["Managed"::[t],obj,freeFunc] 构造一个包含 obj 的托管对象,该对象可在 "Managed" 对象释放时执行 freeFunc[obj]. freeFunc 必须有类型签名 {t}"Null".
- CreateTypeInstance["Managed"::[t],obj] 把 DeleteObject 作为 freeFunc 使用.
- 对于特定的 "Managed"::[t] 类型有许多构造函数,这些构造函数在编译类型 t 的页面上有记录. 例如,"Managed"::["CString"] 的构造函数用 "CString" 来记录.
属性
- 类型为 "Managed"::[t] 的 man 的 Information[man,"BaseType"] 给出 "TypeSpecifier"::[t].
- UnmanageObject 解包并使一个托管对象失效,获取被包装对象的所有权.
UnmanageObject[man] 等同于 man["UnmanageObject"].
运行时错误
- 在用 UnmanageObject 解除管理后使用托管对象,可能会产生运行时错误.
InvalidManaged
范例
打开所有单元 关闭所有单元基本范例 (3)
编译一个返回托管 "CString" 对象的程序:
cf = FunctionCompile[Function[Typed[str, "String"],
Cast[str, "Managed"::["CString"]]
]]cf["Hello, World!"]当托管对象超出范围时,包装的 "CString" 被自动释放:
With[{before = MemoryInUse[]}, Do[cf["test"], 100];MemoryInUse[] - before]编译一个函数,使得该函数可以返回一个释放时会打印出来的托管对象:
cf = FunctionCompile[Function[{},
CreateTypeInstance["Managed", 12, Function[obj, Echo["freed"];]]
]]Module[{obj}, obj = cf[];Echo["body"]];编译一个函数,通过将字符串转换为托管的 C 字符串并使用其借用值来返回字符串的长度:
func = FunctionCompile[
Function[{Typed[str, "String"]}, Module[{cstrMan, cstr, len}, cstrMan = Cast[str, "Managed"::["CString"]];
cstr = cstrMan["BorrowValue"];
len = LibraryFunction["strlen"][cstr];
len
]
]
]func["Hello, World!"]范围 (4)
cf = FunctionCompile[Function[{},
Module[{obj},
obj = CreateTypeInstance["Managed", 12, Function[obj, Echo["freed"];]];
Echo["body"];
]
]]cf[]可以用 UnmanageObject 来访问管理对象的内容:
createManaged = FunctionCompile[Function[{},
CreateTypeInstance["Managed", 12, Function[obj, Echo["freed"];]]
]]unmanage = FunctionCompile[Function[Typed[arg, "Managed"::["MachineInteger"]],
UnmanageObject[arg]
]]man = createManaged[]使用 UnmanageObject 提取其内容:
unmanage[man]UnmanageObject 会使托管对象失效,因此对 UnmanageObject 的后续调用会失败:
unmanage[man]已经解除管理的托管对象不会被自动释放. 编译用于创建和解除管理对象的函数:
createManaged = FunctionCompile[Function[{},
CreateTypeInstance["Managed", 12, Function[obj, Echo["freed"];]]
]]unmanage = FunctionCompile[Function[Typed[arg, "Managed"::["MachineInteger"]],
arg["UnmanageObject"]
]]Module[{obj}, obj = createManaged[];Echo["body"]];Module[{obj}, obj = createManaged[];unmanage[obj];Echo["body"]];dec = LibraryFunctionDeclaration["sumArray", "compilerDemoBase", {"CArray"::["CLong"], "CLong"} -> "CInt"];cf = FunctionCompile[dec,
Function[Typed[arg, "ListVector"::["CLong"]],
Module[{carr},
carr = CreateTypeInstance["Managed"::["CArray"::["CLong"]], arg];
LibraryFunction["sumArray"][carr, Length[arg]]
]
]
]cf[Range[100]]可能存在的问题 (1)
从已被解除托管的托管对象中借用值会导致错误. 为以下操作编写编译函数:从托管对象中创建值、将托管对象解除托管,以及从托管对象中借用值:
createManaged = FunctionCompile[Function[{},
CreateTypeInstance["Managed", 12, Function[obj, Echo["freed"];]]
]]unmanage = FunctionCompile[Function[Typed[arg, "Managed"::["MachineInteger"]],
arg["UnmanageObject"]
]]borrow = FunctionCompile[Function[Typed[arg, "Managed"::["MachineInteger"]],
arg["BorrowValue"]
], CompilerRuntimeErrorAction -> None]man = createManaged[]unmanage[man]borrow[man]技术笔记
历史
2022年引入 (13.1)