> Would that actually work? it does not feel good to allocate a string to 
> convert it to a cstring. What's the best way to do here?

Allocating a string and callind `cstring` does work for passing string.

What I usually do is make a lightweight wrapper on proc like these so I can 
pass string directly :

Here is a typical example, just ask if something is not clear :
    
    
    // example.c
    #include <stddef.h>
    #include <string.h>
    #include <stdio.h>
    
    #define MAX_LEN 255
    
    void  dummy(char bufMsg[MAX_LEN]) {
      strcpy(bufMsg, "azerty"); // This is just a dummy example
      printf("%s \n", bufMsg);
    }
    
    // Sometimes you also have
    void  dummySize(char * bufMsg, size_t bufSize) {
      if(bufSize < 10) {
        printf("C program says: Error buffer too small\n");
        return;
      }
      
      strcpy(bufMsg, "0123456789"); // In reality, check that you don't write 
over bufSize
      printf("%s \n", bufMsg);
    }
    
    
    Run
    
    
    # example.nim
    import strutils
    
    {.compile: "example.c".}
    const MAX_LEN = 255
    
    proc c_dummy(bufMsg: cstring) {.importc: "dummy", cdecl.}
    proc c_dummySize(bufMsg: cstring, bufSize: csize_t) {.importc: "dummySize", 
cdecl.}
    
    proc dummy(): string =
      result = newString(MAX_LEN);
      c_dummy(result.cstring)
      result = $(result.cstring)
    
    proc dummySize(bufSize: int): string =
      result = newString(bufSize);
      c_dummySize(result.cstring, result.len.csize_t)
      # Why do I do that ?
      # Because newString create a buffer of size bufSize full of zeros
      # The C function will not (usually write) in all the memory.
      # result represent as an array now contains : ['0', '1', '2', '3', '4', 
'5,', '6', '7', '8', '9',char(0), char(0), char(0), ..., char(0)]
      # Which is not typically what you want. So converting to cstring and back 
will strip result of '0' char (you can also use strip from std/strutils)
      result = $(result.cstring)
    
    doAssert dummy() == "azerty"
    doAssert dummySize(12) == "0123456789"
    let res = dummySize(5)  # Here you see the printf : your buffer is too small
    doAssert res.isEmptyOrWhitespace() # res is empty because the C didn't 
write any data inside : it's full of char(0)
    
    
    
    Run

I personnaly wouldn't use `array[LEN, char]` to represent `char *` because it 
would be harder to use from Nim side: dealing manually with null termination or 
even simply writing a string in your `array[char]` just wouldn't be practical.

So unless your `char*` is actually a buffer that does not need to be null 
terminated (in which case you really should use `uint8_t*`), I don't recommend 
using array.

Reply via email to