Thread overview
From C to D: issue with arguments for core.stdc.string.memcpy
Feb 20, 2019
Alec Stewart
Feb 20, 2019
Mike Parker
Feb 22, 2019
Meta
Feb 22, 2019
Alec Stewart
February 20, 2019
So I've been close to translating a small single header C library to D for a bit now, and I'm just going to admit that I am no expert in C or D. The exact error I'm getting is

    ... cannot pass argument `(s*).stack.buffer` of type `char[31]`  to parameter `return scope void s1`

Now here's the relevant D code:


    static auto RS_ALIGNMENT() {
        return (void *).sizeof > size_t.sizeof ? (void *).sizeof : size_t.sizeof;
    }

    struct rs_heap
    {
        char* buffer;

        size_t size;

        size_t capacity;

        ubyte[RS_ALIGNMENT - 1] align_;

        ubyte flag;
    }

    enum RS_STACK_CAPACITY = rs_heap.sizeof - 1;


    struct rs_stack
    {

        char[RS_STACK_CAPACITY] buffer;

        ubyte left;
    }

    union rapidstring
    {
        rs_stack stack;

        rs_heap heap;
    }

and what I'm trying to do is

    memcpy(s.stack.buffer, input, n);
    // s is of type rapidstring*
    // input is of type const(char)*
    // and n is size_t


Here's the relevant C code

    #ifndef RS_STACK_CAPACITY
    #define RS_STACK_CAPACITY (sizeof(rs_heap) - 1)
    #endif

    #ifdef RS_STACK_CAPACITY
    #define RS_ALIGNMENT \
	(sizeof(void *) > sizeof(size_t) ? sizeof(void *) : sizeof(size_t))
    #endif

    typedef struct {
	
	char *buffer;

	size_t size;
	
	size_t capacity;

	unsigned char align[RS_ALIGNMENT - 1];
	
	unsigned char flag;
    } rs_heap;

    typedef struct {
	
	char buffer[RS_STACK_CAPACITY];
	
        unsigned char left;
    } rs_stack;

    typedef union {

	rs_stack stack;

	rs_heap heap;
    } rapidstring;

(here's the library I'm translating: https://github.com/boyerjohn/rapidstring)


BUT while in C `memcpy(s->stack.buffer, input, n);` doesn't throw any linter/checker errors (in my editor or on https://repl.it/languages/C), it will return an exit status of -1 (on https://repl.it/languages/C at least) when just testing with

    int main(void) {
      rapidstring* s;
      const char * input;
      size_t n;
      memcpy(s->stack.buffer, input, n);
      printf("Will print if we don't get an exit status of -1");
      return 0;
    }


But thankfully, the Online D Editor actually gives an error when trying


    void main()
    {
        rapidstring* s;
        const(char)* input;
        size_t n;

        import core.stdc.string : memcpy;
        memcpy(s.stack.buffer, input, n);
        import std.stdio : writeln;
        writeln("prints if we don't fail");
    }

The error

    onlineapp.d(42): Error: function core.stdc.string.memcpy(return scope void* s1, scope const(void*) s2, ulong n) is not callable using argument types (char[31], const(char)*, ulong)
    onlineapp.d(42):        cannot pass argument (*s).stack.buffer of type char[31] to parameter return scope void* s1


SO, with all of that; how can I fix this? Do I have to do some ugly type casting?

Sorry if it's a really stupid question.
February 20, 2019
On Wednesday, 20 February 2019 at 20:46:42 UTC, Alec Stewart wrote:

>
> The error
>
>     onlineapp.d(42): Error: function core.stdc.string.memcpy(return scope void* s1, scope const(void*) s2, ulong n) is not callable using argument types (char[31], const(char)*, ulong)
>     onlineapp.d(42):        cannot pass argument (*s).stack.buffer of type char[31] to parameter return scope void* s1
>
>
> SO, with all of that; how can I fix this? Do I have to do some ugly type casting?
>

You're passing a static array where the function expects a pointer.

memcpy(s.stack.buffer.ptr, input, n);
February 22, 2019
On Wednesday, 20 February 2019 at 20:57:26 UTC, Mike Parker wrote:
> On Wednesday, 20 February 2019 at 20:46:42 UTC, Alec Stewart wrote:
>
>>
>> The error
>>
>>     onlineapp.d(42): Error: function core.stdc.string.memcpy(return scope void* s1, scope const(void*) s2, ulong n) is not callable using argument types (char[31], const(char)*, ulong)
>>     onlineapp.d(42):        cannot pass argument (*s).stack.buffer of type char[31] to parameter return scope void* s1
>>
>>
>> SO, with all of that; how can I fix this? Do I have to do some ugly type casting?
>>
>
> You're passing a static array where the function expects a pointer.
>
> memcpy(s.stack.buffer.ptr, input, n);

To expand on this just a bit, in case you're not familiar with D, arrays in D do not decay to a pointer like they do in C. You need to pass s.stack.buffer.ptr instead.
February 22, 2019
On Friday, 22 February 2019 at 16:38:10 UTC, Meta wrote:
> On Wednesday, 20 February 2019 at 20:57:26 UTC, Mike Parker wrote:
>> On Wednesday, 20 February 2019 at 20:46:42 UTC, Alec Stewart wrote:
>>
>>>[...]
>>
>> You're passing a static array where the function expects a pointer.
>>
>> memcpy(s.stack.buffer.ptr, input, n);
>
> To expand on this just a bit, in case you're not familiar with D, arrays in D do not decay to a pointer like they do in C. You need to pass s.stack.buffer.ptr instead.

Ah, that makes sense! Thank you all!