简体   繁体   English

在 Visual Works 图像中创建一个 const char **

[英]Create a const char ** in Visual Works image

How i should create a (const char **) to pass it to a C function?我应该如何创建一个(const char **)将其传递给 C function?

Let say my const char ** is named prompts then:假设我的 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.

So prompts is an array of 64bits where the first 32bits are a pointer to user and the secods 32bits are a pointer to pwd .所以prompts是一个 64 位的数组,其中前 32 位是指向user的指针,而后 32 位是指向pwd的指针。

But the C function is not working.但是 C function 不工作。 In GemStone is working ok with:在 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.

DLLCC offers some API very close to C. DLLCC 提供了一些非常接近 C 的 API。 You need an array of two char pointers.您需要一个包含两个 char 指针的数组。

prompts := CIntegerType char pointerType gcMalloc: 2.

Then you can populate this array like this:然后你可以像这样填充这个数组:

prompts at: 0 put: user.
prompts at: 1 put: pwd.

Note that the indices mimic C like prompts[0]=user; prompts[1]=pwd;请注意,索引模仿 C 就像prompts[0]=user; prompts[1]=pwd; prompts[0]=user; prompts[1]=pwd; . .

Last thing, everything you malloc , you must then free , otherwise you'll get memory leaks.最后一件事,所有你malloc ,你必须然后free ,否则你会得到 memory 泄漏。

That means that you shall better protect all this code with some这意味着您应该更好地保护所有这些代码

["your protected code here"]
    ensure: [prompts free. user free. pwd free]`

...or worse... ……或者更糟……

["your protected code here"]
    ensure:
        [prompts isNil ifFalse: [prompts free].
        "etc..."]`.

In early development, I suggest that you shall better use gcMalloc and gcMalloc: .在早期开发中,我建议您最好使用gcMallocgcMalloc:

AFTER THOUGHTS经过思考

gcMalloc is maybe not a such good idea for user and pwd . gcMalloc对于userpwd来说可能不是一个好主意。

This is because prompts will get a copy of the address of memory contained in user and pwd objects: it will point to same memory zone, but will not point to the Smalltalk objects...这是因为prompts将获得包含在userpwd对象中的 memory 地址的副本:它将指向相同的 memory 区域,但不会指向 Smalltalk 对象...

gcMalloc only monitor the garbage collection of Smalltalk objects. gcMalloc 只监控 Smalltalk 对象的垃圾收集。 Hence, if Smalltalk objects are not more used, C heap might get freed prematurely despite some other objects point to the same C heap...因此,如果不再使用 Smalltalk 对象,C 堆可能会过早释放,尽管其他一些对象指向相同的 C 堆...

Example:例子:

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.
    ^prompts

copyToHeap: creates a CPointer object. copyToHeap:创建一个 CPointer object。 As long as the method is active, its context point to those objects (thru slots on the stack).只要该方法处于活动状态,它的上下文就指向那些对象(通过堆栈上的插槽)。
But after return of this method, there is not any object pointing to the CPointer objects.但是这个方法返回后,没有任何 object 指向 CPointer 对象。
If some garbage collection occur, their associated pointer to C heap will be freed.如果发生一些垃圾回收,它们指向 C 堆的关联指针将被释放。

But prompts still contain reference to already freed memory (the so called dangling pointers).prompts仍然包含对已释放的 memory(所谓的悬空指针)的引用。

DLLCC being very close to C, one must adopt the same care as when writing C code... And double pointers is a source of bugs for the vast majority of C programmers. DLLCC 与 C 非常接近,因此在编写 C 代码时必须采取同样的谨慎措施……而双指针是绝大多数 Z0D61F8370CAD1D412F70B84D143E1 程序员的错误来源。

You shouldn't work directly on the bytes.您不应该直接处理字节。 That doesn't even make sense in C.这在 C 中甚至没有意义。

  1. create a struct with the two char* members, that's easier to declare, to create and to handle.使用两个 char* 成员创建一个结构,这更易于声明、创建和处理。
  2. use #gcCalloc or #gcCopyToHeap in order to allocate memory on the heap that's still automatically freed.使用#gcCalloc#gcCopyToHeap以便在仍然自动释放的堆上分配 memory。 Typically it's safe to use these methods because you only need that memory inside a single method to transfer it to C.通常使用这些方法是安全的,因为您只需要在单个方法中将 memory 传输到 C。 The assumption is that the c-function copies this memory itself in case it needs it later.假设是 c 函数复制这个 memory 本身以防以后需要它。
  3. you can use #memberAt:put: to assign members to the struct.您可以使用#memberAt:put:将成员分配给结构。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM