www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Interfacing with C in 2.066.1

reply "Jason den Dulk" <public2 jasondendulk.com> writes:
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
Nov 08 2014
next sibling parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
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 {}
Nov 08 2014
parent reply "fra" <a b.it> writes:
On Saturday, 8 November 2014 at 10:19:19 UTC, John Colvin wrote:
 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() {}
Oh look, is THIS AGAIN. :(
Nov 08 2014
parent "Gary Willoughby" <dev nomad.so> writes:
On Saturday, 8 November 2014 at 18:28:50 UTC, fra wrote:
 On Saturday, 8 November 2014 at 10:19:19 UTC, John Colvin wrote:
 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() {}
Oh look, is THIS AGAIN. :(
Yeah, this is causing a lot of confusion.
Nov 08 2014
prev sibling next sibling parent reply "Gary Willoughby" <dev nomad.so> writes:
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?
Nov 08 2014
parent reply "Jason den Dulk" <public2 jasondendulk.com> writes:
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.
Nov 08 2014
parent reply "Jason den Dulk" <public2 jasondendulk.com> writes:
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.
Nov 08 2014
parent reply "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"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.
Nov 08 2014
next sibling parent "Sean Kelly" <sean invisibleduck.org> writes:
Or when you declare an instance of the variable, disable 
auto-initialization via "=void", then do a memset(0).
Nov 08 2014
prev sibling parent "Jason den Dulk" <public2 jasondendulk.com> writes:
On Saturday, 8 November 2014 at 16:41:58 UTC, Daniel Murphy wrote:
 This symbol 
 (`_D6jaypha5dbsql5mysql1c5mysql12st_mysql_res6__initZ') is the 
 init data for the struct.
It looks as though the compiler is trying to create a instance of the struct somewhere, but the source code doesn't ask for this. This is evidenced by the fact that when I remove the definition altogether, replacing it with a declaration, it works. The compiler guys may ponder this if they wish. Since a workaround has been found I'll consider the subject closed. A thank you to everyone who contributed. Regards Jason
Nov 08 2014
prev sibling next sibling parent reply Mike Parker <aldacron gmail.com> writes:
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.
Nov 08 2014
parent Mike Parker <aldacron gmail.com> writes:
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.
Nov 08 2014
prev sibling parent Steven Schveighoffer <schveiguy yahoo.com> writes:
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
Nov 08 2014