我想将UninterpretedBytes传递给外部库,比如说这样的话
MyLibrary>>foo: buf len: len
<C: int foo(void *buf,unsigned int len)>
MyApplication>>test
buffer := UninterpretedBytes new: 4.
^MyLibrary new foo: buffer len: buffer size.
但这在CPointerType>>coerceForArgument:anObject
失败了。
我知道我可以使用buffer gcCopyToHeap
,但我不想
我想在Smalltalk内存中使用基于Smalltalk 1的地址处理一个对象,没有额外的副本,也没有任何其他复杂功能。
我发现CPointerType>>coerceForArgument:anObject
的最后一行是可疑的:
(anObject isString
or: [self isOopRef and: [anObject class isBits and: [anObject class isVariable]]])
ifTrue: [^anObject].
self isOopRef
表示CPointerType已声明为_oopref *
如果我作弊并宣布:
MyLibrary>>foo: buf len: len
<C: int foo(_oopref *buf,unsigned int len)>
然后MyApplication new test
按预期工作,但我不想作弊,原型是从C标题中自动提取的,我不想手动修补它们。
self isOopRef
在语义上是指对面向对象指针的引用
每个对象都可以被视为面向对象的指针,因此可以通过引用传递给_oopref *
,除了像SmallInteger SmallDouble Character这样的直接对象。在代码中有一个警卫来检查anObject isImmediate
时的情况,所以在这个阶段,anObject
绝对是一个oop。
这样的_oopref可以在外部C代码中操作,例如通过一些Object Engine函数oe *(),这不仅限于字节数组/单词/双字!
因此,警卫and: [anObject class isBits and: [anObject class isVariable]]
毫无意义。
如果我将CPointerType>>coerceForArgument:anObject
的最后一行修改为:
(anObject isString
or: [self isOopRef or: [anObject class isBits and: [anObject class isVariable]]])
ifTrue: [^anObject].
然后MyApplication new test
就像魅力一样
这不是真正的意图吗?如果原型指定指向oop的指针,则传递任何类型的非立即对象,或者传递对bytes / words /...的数组的引用。