Jump to page: 1 2
Thread overview
Interfacing with C in 2.066.1
Nov 08, 2014
Jason den Dulk
Nov 08, 2014
John Colvin
Nov 08, 2014
fra
Nov 08, 2014
Gary Willoughby
Nov 08, 2014
Gary Willoughby
Nov 08, 2014
Jason den Dulk
Nov 08, 2014
Jason den Dulk
Nov 08, 2014
Daniel Murphy
Nov 08, 2014
Sean Kelly
Nov 09, 2014
Jason den Dulk
Nov 08, 2014
Mike Parker
Nov 08, 2014
Mike Parker
November 08, 2014
When upgrading my compiler from 2.065 to 2.066.1 I have encountered problems with some of my extern(C) code.

My declarations (in a .di file) are wrapped in an extern(C) declaration. The code compiled fine in 2.065. In 2.066.1 it first complained about functions returning "const char *" ("function without this cannot be const"). After removing the offending consts, it now complains of a missing "init" field of a struct.

It looks like its trying to access the stuff as D code rather than C code. Can anyone shed some light on what the problem might be?

Thanks in advance
Jason
November 08, 2014
On Saturday, 8 November 2014 at 10:03:51 UTC, Jason den Dulk wrote:
> When upgrading my compiler from 2.065 to 2.066.1 I have encountered problems with some of my extern(C) code.
>
> My declarations (in a .di file) are wrapped in an extern(C) declaration. The code compiled fine in 2.065. In 2.066.1 it first complained about functions returning "const char *" ("function without this cannot be const").

const char* foo() {}

is a function that takes a const 'this' reference and returns char*
You want
const(char)* foo() {}
or
const(char*) foo() {}

If you do want a const 'this' then you should write:

char* foo() const {}
November 08, 2014
On Saturday, 8 November 2014 at 10:03:51 UTC, Jason den Dulk wrote:
> When upgrading my compiler from 2.065 to 2.066.1 I have encountered problems with some of my extern(C) code.
>
> My declarations (in a .di file) are wrapped in an extern(C) declaration. The code compiled fine in 2.065. In 2.066.1 it first complained about functions returning "const char *" ("function without this cannot be const"). After removing the offending consts, it now complains of a missing "init" field of a struct.
>
> It looks like its trying to access the stuff as D code rather than C code. Can anyone shed some light on what the problem might be?
>
> Thanks in advance
> Jason

This is highlighting the problem that using const in a function declaration can lead to confusion. Look at this example:

const char* foo()

Here const is interpreted as an attribute of the function not the char type. So defining it as a type constructor will remove the confusion like this:

const(char)* foo()

Here we are declaring a pointer to a const char which is (if you're interfacing with C) what you want. I'm assuming the compiler is being more strict about this now?

There was a forum thread somewhere detailing a proposition to only accept function attributes on the right of the declaration to avoid this confusion but i think it was just thoughts.

Have you got an example of the struct giving you problems?
November 08, 2014
On 11/8/2014 7:03 PM, Jason den Dulk wrote:

>
> It looks like its trying to access the stuff as D code rather than C
> code. Can anyone shed some light on what the problem might be?

Anything in an extern(C) block *is* D code. The extern(C) bit just affects the name mangling.

November 08, 2014
On 11/8/2014 8:43 PM, Mike Parker wrote:
> On 11/8/2014 7:03 PM, Jason den Dulk wrote:
>
>>
>> It looks like its trying to access the stuff as D code rather than C
>> code. Can anyone shed some light on what the problem might be?
>
> Anything in an extern(C) block *is* D code. The extern(C) bit just
> affects the name mangling.
>

And the calling convention for functions, actually.
November 08, 2014
On Saturday, 8 November 2014 at 10:52:16 UTC, Gary Willoughby wrote:

> const(char)* foo()

This fixed the const issue. Thanks for that guys.

> Have you got an example of the struct giving you problems?

struct st_mysql_res {
  my_ulonglong  row_count;
  MYSQL_FIELD	*fields;
  MYSQL_DATA	*data;
  MYSQL_ROWS	*data_cursor;
  ulong *lengths;		/* column lengths of current row */
  MYSQL		*handle;		/* for unbuffered reads */
  st_mysql_methods *methods;
  MYSQL_ROW	row;			/* If unbuffered read */
  MYSQL_ROW	current_row;		/* buffer to current row */
  MEM_ROOT	field_alloc;
  uint	field_count, current_field;
  my_bool	eof;			/* Used by mysql_fetch_row */
  /* mysql_stmt_close() had to cancel this result */
  my_bool       unbuffered_fetch_cancelled;
  void *extension;
}

The struct is never instantised anywhere. It is always referenced by pointer.

The error message is:
undefined reference to `_D6jaypha5dbsql5mysql1c5mysql12st_mysql_res6__initZ'

A search of the raw object file generated produces the above reference, however when disassembling the file, it disappears. Not sure what the significance of that is.
November 08, 2014
Some extra insight.

In the struct "my_bool" is a char alias. I change it to a byte, it compiles. I change it back to char, it dies.
November 08, 2014
On 11/8/14 5:03 AM, Jason den Dulk wrote:

> My declarations (in a .di file) are wrapped in an extern(C) declaration.
> The code compiled fine in 2.065. In 2.066.1 it first complained about
> functions returning "const char *" ("function without this cannot be
> const").

BTW, the code as compiled in 2.065 was returning char *, not const char *. So the new compiler fixed a bug in your code :)

-Steve
November 08, 2014
"Jason den Dulk"  wrote in message news:mobvaeuhbjujojfaycgn@forum.dlang.org...

> Some extra insight.
>
> In the struct "my_bool" is a char alias. I change it to a byte, it compiles. I change it back to char, it dies.

This symbol (`_D6jaypha5dbsql5mysql1c5mysql12st_mysql_res6__initZ') is the init data for the struct.

D's char's default value is 0xFF.

When structs can be initialized by memsetting to zero, they don't need an init symbol.

So you have a few options:
- Don't use char, use something like bool or ubyte that has 0 as the default value.  When interfacing with C you only need to match size (and sometimes sign) for C's integral types.
- Give the struct member a default value of false
- Compile the .di file like you do the rest of your source, so the init symbol gets found correctly. 

November 08, 2014
Or when you declare an instance of the variable, disable auto-initialization via "=void", then do a memset(0).
« First   ‹ Prev
1 2