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