exern (C) linkage problem

Lars T. Kyllingstad public at kyllingen.NOSPAMnet
Mon Jul 19 03:20:22 PDT 2010


On Sun, 18 Jul 2010 13:08:57 -0700, Charles Hixson wrote:

> I'm trying to link a C routine to a D program, passing string
> parameters, but I keep getting segmentation errors. As you can see,
> these are simple test routines, so the names don't reflect current
> status, but merely where I intend to arrive...but I've hit severe
> roadblocks.
> (FWIW, I've tried including -fpic in the gcc command, and it didn't
> appear to make any difference.)
> 
> Makefile:
> biblio: biblio.d sqlitebase.o
> 	dmd	biblio.d sqlitebase.o -ofbiblio
> 
> sqlitebase.o: sqlitebase.c sqlitebase.h
> 	gcc -c sqlitebase.c
> 
> biblio.d:
> import   std.stdio;
> 
> //extern (C)   void   dbdefine (char[] str); extern (C)   void  
> dbdefine (char[] inStr, ref char[255] outStr);
> 
> void   main()
> {  char[255]   retVal;
>     char[]   msg   =   cast(char[])"Hello from C\0"; dbdefine   (msg,
>     retVal);
>     writeln ("Hello, World");
> }
> 
> sqlitebase.h:
> 
> //void   dbdefine (char str[]);
> void   dbdefine (char inStr[], char outStr[255]);
> 
> sqlitebase.c:
> 
> #include   "sqlitebase.h"
> 
> //void   dbdefine (char str[])
> void   dbdefine (char inStr[], char outStr[255]) {   //int   i   =   0;
>     //while (str[i] != 0)   i++;
>     //printStr   (i, str);
>     //^^--segmentation fault--^^
>     //   printf ("%s/n", str);
>     //^^--warning: incompatible implicit declaration of built-in
> function ‘printf’--^^
>     //int   i   =   str[0];
>     //putchar(i);
>     //^^--segmentation fault--^^
>     int   i   =   -1;
>     while (++i < 255)
>     {   if (inStr[i] == 0)   break;
>        outStr[i]   =   inStr[i];
>     }
> 
> }


Since bearophile already answered with a solution to your problem, I'll 
just chime in with a few small tips (of which you may already be aware):

1. D string *literals* are already zero-terminated, so you don't need to 
add the \0 character explicitly.  Also, they cast implicitly to const
(char)*, so if your function doesn't change inStr, it's perfectly fine to 
do

  extern(C) void dbdefine (const char* inStr);
  dbdefine("Hello from C");

2. For D strings in general the \0 must be added, but this is very easy 
to forget.  Therefore, when passing strings to C functions I always use 
the std.string.toStringz() function.  It takes a D string, adds a \0 if 
necessary, and returns a pointer to the first character.

  string s = getAStringFromSomewhere();
  dbdefine(toStringz(s));

-Lars


More information about the Digitalmars-d-learn mailing list