www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - cooperation between D and C

reply Tiago Gasiba <tiago.gasiba gmail.com> writes:
Hi all,

  I just recently downloaded the D linux compiler dmd and started playing
around with it. D programming language is completely new to me but my
general impression is that it is great! It allows me to write some routines
I've previously implemented in C much faster and without memory leakages.
  I should say that I'm a PhD student in Germany doing its research in a big
company. In this company it is quite usual to use C programming language
but, since I'm doing research, I'm free to use the tools I want to achieve
my purpose.
  When integrating developed routines (from me or from other colleges for
example) into bigger projects, normally two approaches are normally taken:
creating a linux library (put in /usr/lib for example), or an object file
(.o) to be included and used directly for compilation, if the proper header
files (.h) are present.

  My question is the following: If I use D to develop software and later on
I or someone else needs to integrate the routines into a larger project,
how can this be done? I've read something about using C routines in D but,
is it possible to do it the other way around? What happens with the memory
allocation routines and the garbage collector?
  If this is possible to be done, can someone please provide me with a
simple example such that I can start toying around?

  Thanks,
  Tiago Gasiba
Jun 14 2005
next sibling parent reply "Regan Heath" <regan netwin.co.nz> writes:
Yes, it's possible, in short you specify C linkage for the exported D  
functions.

Yes, the GC causes problems, for example if you pass some memory to the C  
code, but no longer have a reference in the D code, the GC may collect it.  
The solution is probably to keep a list of memory in the D code, and  
explicitly free it from the C code, or to use malloc to obtain the memory,  
or to avoid doing this alltogether.

Have a quick look at the " Calling D code from C" thread in this NG. Also  
the "Calling D functions from C" thread in the digitalmars.D NG.

Regan

On Wed, 15 Jun 2005 03:31:09 +0200, Tiago Gasiba <tiago.gasiba gmail.com>  
wrote:
 Hi all,

   I just recently downloaded the D linux compiler dmd and started playing
 around with it. D programming language is completely new to me but my
 general impression is that it is great! It allows me to write some  
 routines
 I've previously implemented in C much faster and without memory leakages.
   I should say that I'm a PhD student in Germany doing its research in a  
 big
 company. In this company it is quite usual to use C programming language
 but, since I'm doing research, I'm free to use the tools I want to  
 achieve
 my purpose.
   When integrating developed routines (from me or from other colleges for
 example) into bigger projects, normally two approaches are normally  
 taken:
 creating a linux library (put in /usr/lib for example), or an object file
 (.o) to be included and used directly for compilation, if the proper  
 header
 files (.h) are present.

   My question is the following: If I use D to develop software and later  
 on
 I or someone else needs to integrate the routines into a larger project,
 how can this be done? I've read something about using C routines in D  
 but,
 is it possible to do it the other way around? What happens with the  
 memory
 allocation routines and the garbage collector?
   If this is possible to be done, can someone please provide me with a
 simple example such that I can start toying around?

   Thanks,
   Tiago Gasiba

Jun 14 2005
parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
Regan Heath wrote:
 Yes, it's possible, in short you specify C linkage for the exported D  
 functions.
 
 Yes, the GC causes problems, for example if you pass some memory to the 
 C  code, but no longer have a reference in the D code, the GC may 
 collect it.  The solution is probably to keep a list of memory in the D 
 code, and  explicitly free it from the C code, or to use malloc to 
 obtain the memory,  or to avoid doing this alltogether.

Yes, keeping a pointer on the D side works at the moment, but it might not work once a copying GC is out. D/26273 Stewart. -- My e-mail is valid but not my primary mailbox. Please keep replies on the 'group where everyone may benefit.
Jun 15 2005
next sibling parent Tiago Gasiba <Tiago_member pathlink.com> writes:
Hi all,

Where can I get the dstub.d and cstub.c in order to compile D libraries in C?
Googling around I could find nothing, and the links given in the thread:
www.digitalmars.com/d/archives/ digitalmars/D/learn/630.html do not exist
anymore...

Thanks!
Jun 15 2005
prev sibling parent reply Tiago Gasiba <tiago.gasiba gmail.com> writes:
Hi all,

What am I doing wrong in the following code?
The idea is to try to pass some values (through a variable) from a function
in D into a function in C. 
The code compiles w/o problems, but does not execute properly - its gets a
Segmentation fault.

---------------- (SOURCE) ----------------
-------- Makefile -------- 
C           = gcc
D           = dmd
LIB_OPTS_D  = -c -w -g
LIB_OPTS_C  = -c -Wall -g
OPTS_C      = -Wall -g

all:  teste

teste: teste.o libd.o
        $(C) $(OPTS_C) -o teste teste.o libd.o -lphobos -lpthread -lm

teste.o: teste.c
        $(C) $(LIB_OPTS_C) teste.c

libd.o: libd.d
        $(D) $(LIB_OPTS_D) libd.d

clean:
        $(RM) teste
        $(RM) *.o

-------- teste.c -------- 
#include <stdio.h>
#include <stdlib.h>


int func2( int * );


int main( int argc, char **argv ){
  int *X, i, n;

  n = func(X);

  for( i=0; i<n; i++ )
    printf("%d\n",X[i]);

  return 0;
}

-------- libd.d -------- 
module libd;

const int  LEN = 2;

extern (C) int func( int *X ){
  printf("func - 1\n");
  int [] Y;
  printf("func - 2\n");
  Y.length=LEN;
  printf("func - 3\n");
  Y[] = 4;
  printf("func - 4\n");
  X = Y;
  printf("func - 5\n");
  return LEN;
}


int main( char [][]argv ){
  return 0;
}
---------------- (END) ----------------

Tiago
Jun 15 2005
next sibling parent reply "Walter" <newshound digitalmars.com> writes:
You have both a main() in the C program, and a main() in the D program. This
will prevent the D startup code from being executed - see the code in
phobos/internal/dmain2.d.
Jun 15 2005
parent reply Tiago Gasiba <tiago.gasiba gmail.com> writes:
Walter wrote:

 You have both a main() in the C program, and a main() in the D program.
 This will prevent the D startup code from being executed - see the code in
 phobos/internal/dmain2.d.

Great! I have done some changes (shown later in the email), and now the code compiles and does not give any segmentation fault. The solution I have found is pretty ugly, but it works. However, the C function does not get the correct values from D! I get the following result, by executing the program: gasiba linux:~/D/D in C> ./teste Entering D... func - 1 func - 2 func - 3 func - 4 func - 5 4 4 Leaving D... 134566464 134566644 ---------------- (CHANGED FILES) ---------------- -------- teste.c -------- #include <stdio.h> #include <stdlib.h> int func( int * ); int main2( void ){ int *X, i, n; n = func(X); for( i=0; i<n; i++ ) printf("%d\n",X[i]); return 0; } -------- libd.d -------- module libd; const int LEN = 2; extern (C) int func( int *X ){ printf("Entering D...\n"); printf("func - 1\n"); int [] Y; printf("func - 2\n"); Y.length=LEN; printf("func - 3\n"); Y[] = 4; printf("func - 4\n"); X = Y; printf("func - 5\n"); for( int i=0; i<Y.length; i++ ) printf("%d\n",X[i]); printf("Leaving D...\n"); return LEN; } extern (C) int main2(); int main( char [][]argv ){ return main2(); } ---------------- (END) ---------------- Tiago
Jun 15 2005
next sibling parent reply Tom S <h3r3tic remove.mat.uni.torun.pl> writes:
Tiago Gasiba wrote:
 Great!
 I have done some changes (shown later in the email), and now the code
 compiles and does not give any segmentation fault.
 The solution I have found is pretty ugly, but it works.
 However, the C function does not get the correct values from D!

 extern (C) int func( int *X ){
   printf("Entering D...\n");
   printf("func - 1\n");
   int [] Y;
   printf("func - 2\n");
   Y.length=LEN;
   printf("func - 3\n");
   Y[] = 4;
   printf("func - 4\n");
   X = Y;

You're modifying a local copy of the pointer, not the one that you have in your C function. -- Tomasz Stachowiak /+ a.k.a. h3r3tic +/
Jun 15 2005
parent "Regan Heath" <regan netwin.co.nz> writes:
On Thu, 16 Jun 2005 00:15:34 +0200, Tom S  
<h3r3tic remove.mat.uni.torun.pl> wrote:
 Tiago Gasiba wrote:
 Great!
 I have done some changes (shown later in the email), and now the code
 compiles and does not give any segmentation fault.
 The solution I have found is pretty ugly, but it works.
 However, the C function does not get the correct values from D!

 extern (C) int func( int *X ){
   printf("Entering D...\n");
   printf("func - 1\n");
   int [] Y;
   printf("func - 2\n");
   Y.length=LEN;
   printf("func - 3\n");
   Y[] = 4;
   printf("func - 4\n");
   X = Y;

You're modifying a local copy of the pointer, not the one that you have in your C function.

I think it's even worse than that. The variable 'Y' is on the stack of the function 'func' and can thus be collected/destroyed after the function has returned. Try: -------- teste.c -------- #include <stdio.h> #include <stdlib.h> int func( int ** ); int main2( void ){ int *X, i, n; n = func(&X); for( i=0; i<n; i++ ) printf("%d\n",X[i]); return 0; } -------- libd.d -------- module libd; const int LEN = 2; int[LEN] Y; extern(C) int func(int **X) { Y[] = 4; *X = Y.ptr; } extern (C) int main2(); int main( char [][]argv ){ return main2(); } Regan
Jun 15 2005
prev sibling parent "Walter" <newshound digitalmars.com> writes:
"Tiago Gasiba" <tiago.gasiba gmail.com> wrote in message
news:d8q89d$u0g$1 digitaldaemon.com...
 int main2( void ){
   int *X, i, n;

   n = func(X);

Looks to me like X is not initialized before it is passed to func(), meaning that garbage is passed.
Jun 16 2005
prev sibling parent Tiago Gasiba <tiago.gasiba gmail.com> writes:
Hi *,

Sorry, small mistake with copy-paste - the prototype of the D function (in
the file teste.c) is obviously:
  int func( int * );
and not func2 as in my previous post.
Still, the question remains, where is the bug? :)

Thanks,
Tiago
Jun 15 2005
prev sibling parent reply Tiago Gasiba <tiago.gasiba gmail.com> writes:
Hi *,

Thanks you all for the help.
I have successfully written and tested a D routine running in a C project.
I have written a small tutorial, which you can access through my webpage
http://www.gasiba.de under the link "D". Since I'm not a D-guru (in fact
I'm a complete novice), please feel free to comment on what I have written.

The next question which I would like to ask is, how can I integrate the D
startup code, ie gc_init() and others (from dmain2.d), into the C startup
code just by linkage. I know the entry point to C is the _start() routine
which then calls main(). How can I include some code after the _start(),
but before main() such that I'm not required to explicitly call gc_init()
in my C project?

Thanks,
Tiago
Jun 17 2005
parent reply Brad Beveridge <brad somewhere.net> writes:
Tiago Gasiba wrote:
 Hi *,
 
 Thanks you all for the help.
 I have successfully written and tested a D routine running in a C project.
 I have written a small tutorial, which you can access through my webpage
 http://www.gasiba.de under the link "D". Since I'm not a D-guru (in fact
 I'm a complete novice), please feel free to comment on what I have written.
 
 The next question which I would like to ask is, how can I integrate the D
 startup code, ie gc_init() and others (from dmain2.d), into the C startup
 code just by linkage. I know the entry point to C is the _start() routine
 which then calls main(). How can I include some code after the _start(),
 but before main() such that I'm not required to explicitly call gc_init()
 in my C project?
 
 Thanks,
 Tiago
 

special library init function that automatically gets called upon library load - I'm not sure what this is, but it is standard for all .so files. If you're just making .o files I don't know - I'd suggest having a single "d_init()" function that gets called. Brad
Jun 17 2005
parent reply Tiago Gasiba <tiago.gasiba gmail.com> writes:
Brad Beveridge wrote:

 If you are making a library (rather than just a .o), there should be a
 special library init function that automatically gets called upon
 library load - I'm not sure what this is, but it is standard for all .so
 files.
 If you're just making .o files I don't know - I'd suggest having a
 single "d_init()" function that gets called.
 
 Brad

Sometimes I confuse the word library with object, i.e. .o files. Sorry. Yes, for now, I'm only interested in generating .o files from D and linking them to a C project. What I would like to avoid is to manually call d_init() in the main() function - this should be done somehow automatically when linking with the D objects. To avoid linker errors in case I decide to use several D .o files, the changes would have to be shifted to, say libphobos; am I right? A simple solution would be to quit the idea of having main() in C and rename it to C_main() for example. Then, a properly designed main() function from D would call C_main(). BUT, this introduces changes to the C project that I'm trying to avoid. BR, Tiago
Jun 17 2005
parent Brad Beveridge <brad somewhere.net> writes:
Tiago Gasiba wrote:

 Sometimes I confuse the word library with object, i.e. .o files. Sorry.
 Yes, for now, I'm only interested in generating .o files from D and linking
 them to a C project. What I would like to avoid is to manually call
 d_init() in the main() function - this should be done somehow automatically
 when linking with the D objects. To avoid linker errors in case I decide to
 use several D .o files, the changes would have to be shifted to, say
 libphobos; am I right?
 A simple solution would be to quit the idea of having main() in C and rename
 it to C_main() for example.
 Then, a properly designed main() function from D would call C_main().
 BUT, this introduces changes to the C project that I'm trying to avoid.
 
 BR,
 Tiago

That is a tough problem I think. I wonder if something along the lines of the following will work: 1) Create a CPP file that has a static class instance, that classes constructor sets up D 2) Link the CPP .o file and D's .o files to the original C project I've seen a similar trick when using dlopen to load dynamic libraries. So if the above works & the CPP static instance correctly sets up D, then there must be some special "run me first" function for .o files, which you could then look at and generate in a less convoluted fashion. Good luck - sounds like you may need it :) Brad
Jun 17 2005