我应该如何创建一个(const **)来将它传递给一个C函数?
假设我的const char **命名为prompts,那么:
user := 'User:' copyToHeap: #malloc:.
pwd := 'Password:' copyToHeap: #malloc:.
prompts := (ByteArray new: 64) copyToHeap: #malloc:.
prompts copyAt: 0 from: (user referentAddress asByteArraySize: 32) size: 4 startingAt: 1.
prompts copyAt: 31 from: (pwd referentAddress asByteArraySize: 32) size: 4 startingAt: 1.因此,prompts是一个64位数组,其中前32位是指向user的指针,secods 32位是指向pwd的指针。
但是C函数不起作用。在GemStone中,可以使用:
prompts := CByteArray gcMalloc: 16.
user := CByteArray withAll: 'User:'.
pwd := CByteArray withAll: 'Password:'.
prompts uint64At: 0 put: user memoryAddress.
prompts uint64At: 8 put: pwd memoryAddress.发布于 2021-02-20 08:27:26
DLLCC提供了一些非常接近C的API。您需要一个由两个字符指针组成的数组。
prompts := CIntegerType char pointerType gcMalloc: 2.然后,您可以像这样填充这个数组:
prompts at: 0 put: user.
prompts at: 1 put: pwd.请注意,索引与C类似,类似于prompts[0]=user; prompts[1]=pwd;。
最后一件事,所有你的malloc,你必须然后free,否则你会得到内存泄漏。
这意味着您应该更好地使用一些
["your protected code here"]
ensure: [prompts free. user free. pwd free]`...or更糟..。
["your protected code here"]
ensure:
[prompts isNil ifFalse: [prompts free].
"etc..."]`.在早期开发中,我建议您最好使用gcMalloc和gcMalloc:。
后思考
gcMalloc对user和pwd来说可能不是一个好主意。
这是因为prompts将获得包含在user和pwd对象中的内存地址的副本:它将指向相同的内存区域,但不会指向Smalltalk对象.
gcMalloc只监视Smalltalk对象的垃圾收集。因此,如果Smalltalk对象不被更多地使用,C堆可能会过早地被释放,尽管其他一些对象指向同一个C堆.
示例:
fillPrompts
| user pwd prompts |
user := 'User:' copyToHeap: #gcMalloc:.
pwd := 'Password:' copyToHeap: #gcMalloc:.
prompts := CIntegerType char pointerType gcMalloc: 2.
prompts at: 0 put: user.
prompts at: 1 put: pwd.
^promptscopyToHeap:创建一个CPointer对象。只要该方法是活动的,它的上下文就指向这些对象(堆栈上的槽)。
但是在返回此方法后,没有任何对象指向CPointer对象。
如果发生了一些垃圾回收,它们与C堆的关联指针将被释放。
但是prompts仍然包含对已经释放的内存的引用(所谓的悬空指针)。
DLLCC与C非常接近,在编写C代码时必须采取同样的谨慎措施.对于绝大多数C程序员来说,双指针是bug的来源。
发布于 2021-02-20 09:26:46
您不应该直接处理字节。这在C中根本没有意义。
#gcCalloc或#gcCopyToHeap来在堆上分配内存,而堆上的内存仍然是自动释放的。通常,使用这些方法是安全的,因为您只需要将单个方法中的内存传递给C。假设c-函数复制这个内存本身,以防以后需要它。#memberAt:put:将成员分配给struct.。
https://stackoverflow.com/questions/66282875
复制相似问题