www.digitalmars.com         C & C++   DMDScript  

D.gnu - Using D from C

reply Artem Gr <artem bizlink.ru> writes:
Is there some function to initialize the D,
like JvCreateJavaVM in GCJ CNI?

8<--- Test.d ------->8

class DeeTest {
   void test(){
     printf( "D" );
   }
}
extern( C ){
   void testFunction(){
     DeeTest deeTest = new DeeTest();
     deeTest.test();
   }
}

8<--- main.c ------->8

void testFunction();
int main( char** argv, int argc ){
   testFunction();
   return 0;
}

8<--- Problem ------->8

(gdb) run
Starting program: /home/Glim/dee/c_test.exe

Program received signal SIGSEGV, Segmentation fault.
0x0040311c in _d_newclass ()
(gdb) bt
#0  0x0040311c in _d_newclass ()
#1  0x004010c1 in testFunction () at ru/glim/deetest/Test.d:8
#2  0x0040107f in main (argv=0x1, argc=4726336) at main.c:3
(gdb)
Aug 21 2005
parent reply =?ISO-8859-15?Q?Thomas_K=FChne?= writes:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Artem Gr schrieb:
 
 Is there some function to initialize the D,
 like JvCreateJavaVM in GCJ CNI?

Have a look at the code below. Thomas ========== dmd -c phobosc.d some.d gcc -o main main.c some.o phobosc.o -lphobos -lpthread -lm ./main =====phobosc.d===== /* enable access to D code from C Copyright (C) 2005 Thomas Kuehne <thomas kuehne.cn> Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. Redistributions of source code must retain the above copyright notice, definition, disclaimer, and this list of conditions. 2. Redistributions in binary form must reproduce the above copyright notice, definition, disclaimer, and this list of conditions in documentation and/or other materials provided with the distribution. 3. Altered versions must be plainly marked as such and must not be misrepresented as being the original source. */ module kuehne.phobosc; private{ import std.c.stdio; import std.c.stdlib; extern (C) void _STI_monitor_staticctor(); extern (C) void _STD_monitor_staticdtor(); extern (C) void _STI_critical_init(); extern (C) void _STD_critical_term(); extern (C) void gc_init(); extern (C) void gc_term(); extern (C) void _minit(); extern (C) void _moduleCtor(); extern (C) void _moduleDtor(); extern (C) void _moduleUnitTests(); // sometimes required by the linker extern(C) void* _deh_beg; extern(C) void *_deh_end; // protect D memory against GC size_t[void*] memoryGuard; Object sync; // cope with multiple inits & unloads size_t loadCount; } /* call before the use of any D code * multiple calls */ public extern(C) int loadPhobos(){ if(loadCount==0){ version (linux){ _STI_monitor_staticctor(); _STI_critical_init(); gc_init(); } version (Win32){ gc_init(); _minit(); } try{ _moduleCtor(); _moduleUnitTests(); sync = new Object(); }catch(Object o){ fprintf(stderr, "Error: %.*s", o.toString()); return 0; } } loadCount++; return 0; } public extern(C) void unloadPhobos(){ if(loadCount==1){ _moduleDtor(); gc_term(); version (linux){ _STD_critical_term(); _STD_monitor_staticdtor(); } } if(loadCount>0){ loadCount--; } } /* protect memory allocated by D's GC to be collected * while storing the memory in some C code */ public extern(C) void markMemoryFromD(void* ptr){ synchronized(sync){ if(ptr in memoryGuard){ memoryGuard[ptr]+=1; }else{ memoryGuard[ptr]=1; } } } /* remove GC collection guard if no further mark is set */ public extern(C) void unmarkMemoryFromD(void* ptr){ synchronized(sync){ if(ptr in memoryGuard){ if(--memoryGuard[ptr] == 0){ memoryGuard.remove(ptr); } } } } /* remove GC collection guard */ public extern(C) void forceUnmarkMemoryFromD(void* ptr){ if(ptr in memoryGuard){ memoryGuard.remove(ptr); } } =====phobosc.h===== #ifndef PHOBOSC_H #define PHOBOSC_H int loadPhobos(); void unloadPhobos(); void markMemoryFromD(void* ptr); void unmarkMemoryFromD(void* ptr); void forceUnmarkMemoryFromD(void* ptr); #endif =====main.c===== #include "phobosc.h" extern void* _D4some5test1FZC1c6Sample(); // D linkage extern void* test2(void*); // C linkage int main(){ loadPhobos(); void* a = _D1c5test1FZC1c6Sample(); markMemoryFromD(a); void* b = _D1c5test1FZC1c6Sample(); markMemoryFromD(b); test2(a); test2(a); test2(b); test2(a); unmarkMemoryFromD(a); unmarkMemoryFromD(b); unloadPhobos(); return 0; } =====some.d==== module some; import std.stdio; class Sample : Object{ int id; static int idCounter; this(){ id=(idCounter++); } } Sample test1(){ Sample o = new Sample; writef("test1 id:%s\n", o.id); return o; } extern(C) void test2(Sample o){ writef("test2 id:%s\n", o.id); } -----BEGIN PGP SIGNATURE----- iD8DBQFDDQP13w+/yD4P9tIRAt32AKDHQzCzp6nxoUkKZGd/5PgbdjUCiwCfRRPh 3yoHkO8ToOv5PxdE0LS2nKk= =cX0r -----END PGP SIGNATURE-----
Aug 24 2005
parent reply Carlos Santander <csantander619 gmail.com> writes:
Thomas Kühne escribió:
 private{
 	import std.c.stdio;
 	import std.c.stdlib;
 
 	extern (C) void _STI_monitor_staticctor();
 	extern (C) void _STD_monitor_staticdtor();
 	extern (C) void _STI_critical_init();
 	extern (C) void _STD_critical_term();
 	extern (C) void gc_init();
 	extern (C) void gc_term();
 	extern (C) void _minit();
 	extern (C) void _moduleCtor();
 	extern (C) void _moduleDtor();
 	extern (C) void _moduleUnitTests();
 
 	// sometimes required by the linker
 	extern(C) void* _deh_beg;
 	extern(C) void *_deh_end;
 
 	// protect D memory against GC
 	size_t[void*] memoryGuard;
 	Object sync;
 
 	// cope with multiple inits & unloads
 	size_t loadCount;
 }
 
 /* call before the use of any D code
  * multiple calls
  */
 public extern(C) int loadPhobos(){
 	if(loadCount==0){
 		version (linux){
 			_STI_monitor_staticctor();
 			_STI_critical_init();
 			gc_init();
 		}
 
 		version (Win32){
 			gc_init();
 			_minit();
 		}
 
 		try{
 			_moduleCtor();
 			_moduleUnitTests();
 			sync = new Object();
 		}catch(Object o){
 			fprintf(stderr, "Error: %.*s", o.toString());
 			return 0;
 		}
 	}
 
 	loadCount++;
 
 	return 0;
 }
 
 public extern(C) void unloadPhobos(){
 	if(loadCount==1){
 		_moduleDtor();
 		gc_term();
 		version (linux){
 
 			_STD_critical_term();
 			_STD_monitor_staticdtor();
 		}
 
 	}
 
 	if(loadCount>0){
 		loadCount--;
 	}
 }
 

I'm trying to do this but from C but Pascal (using FreePascal 2.0.0) on Mac OS X 10.3.9, but I get "Bus error" all the time. gdb shows this: Program received signal EXC_BAD_ACCESS, Could not access memory. 0x9001f898 in malloc_create_zone () (gdb) bt #0 0x9001f898 in malloc_create_zone () #1 0x9002c424 in _malloc_initialize () #2 0x90001a00 in malloc () #3 0x000042e8 in gc_init () at ../../../gcc-3.4.3/libphobos/internal/gc/gc.d:106 #4 0x00001958 in Dinit () at d.d:32 #5 0x8fe1a278 in __dyld__dyld_start () Any ideas? -- Carlos Santander Bernal
Aug 30 2005
parent reply =?ISO-8859-1?Q?Thomas_K=FChne?= <thomas-dloop kuehne.cn> writes:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Carlos Santander schrieb:
[snip]

 I'm trying to do this but from C but Pascal (using FreePascal 2.0.0) on
 Mac OS X 10.3.9, but I get "Bus error" all the time. gdb shows this:
 
 Program received signal EXC_BAD_ACCESS, Could not access memory.
 0x9001f898 in malloc_create_zone ()
 (gdb) bt
 #0  0x9001f898 in malloc_create_zone ()
 #1  0x9002c424 in _malloc_initialize ()
 #2  0x90001a00 in malloc ()
 #3  0x000042e8 in gc_init () at
 ../../../gcc-3.4.3/libphobos/internal/gc/gc.d:106
 #4  0x00001958 in Dinit () at d.d:32
 #5  0x8fe1a278 in __dyld__dyld_start ()
 
 Any ideas?

Please try the code below - it seems to work on Linux and Windows. If it isn't working properly compile with "-debug=StdioInit" and/or execute the sniplet below BEFORE calling loadPhobos. Thomas - -------------------------------------------- private import gcc.gc_guess_stack; // // argv from C's: int main(int argc, char **argv) // extern(C) setStackOriginGuess(char **argv){ stackOriginGuess = &argv; } - -------------------------------------------- /* enable access to D code from C Copyright (C) 2005 Thomas Kuehne <thomas kuehne.cn> Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. Redistributions of source code must retain the above copyright notice, definition, disclaimer, and this list of conditions. 2. Redistributions in binary form must reproduce the above copyright notice, definition, disclaimer, and this list of conditions in documentation and/or other materials provided with the distribution. 3. Altered versions must be plainly marked as such and must not be misrepresented as being the original source. */ module kuehne.phobosc; private{ // only required for error reporting import std.c.stdio; import std.c.stdlib; // cope with DMD's and GDC's version war version(Unix){}else version(linux){version=Unix;} extern (C) void gc_init(); extern (C) void gc_term(); extern (C) void _moduleCtor(); extern (C) void _moduleDtor(); extern (C) void _moduleUnitTests(); version(Unix){ extern (C) void _STI_monitor_staticctor(); extern (C) void _STD_monitor_staticdtor(); extern (C) void _STI_critical_init(); extern (C) void _STD_critical_term(); } version(Windows){ extern (C) void _minit(); } // sometimes required by the linker extern(C) void* _deh_beg; extern(C) void *_deh_end; // protect D memory against GC size_t[void*] memoryGuard; Object sync; debug(StdioInit){ extern(C) void _d_gnu_cbridge_init_stdio(); } // cope with multiple inits & unload size_t loadCount; } /** call before the use of any D code multiple calls are harmle returns 0 for succe */ public extern(C) int loadPhobos(){ if(loadCount==0){ version (Windows){ gc_init(); _minit(); }else version(Unix){ _STI_monitor_staticctor(); _STI_critical_init(); gc_init(); }else{ pragma(msg, "missing GC init"); static assert(0); } debug(StdioInit){ _d_gnu_cbridge_init_stdio(); } try{ _moduleCtor(); _moduleUnitTests(); sync = new Object(); }catch(Object o){ fprintf(stderr, "Error: %.*s", o.toString()); return 1; } } loadCount++; return 0; } /** don't use any D code or GCed memory after calling thi remember to call unloadPhobos as many times as loadPhobos succeeded */ public extern(C) void unloadPhobos(){ if(loadCount==1){ _moduleDtor(); gc_term(); version(Unix){ _STD_critical_term(); _STD_monitor_staticdtor(); } } if(loadCount>0){ loadCount--; } } /** protect memory allocated by D's GC to be collected while storing the memory in some C code */ public extern(C) void markMemoryFromD(void* ptr){ synchronized(sync){ size_t* count = ptr in memoryGuard; if(count){ (*count)++; }else{ memoryGuard[ptr]=1; } } } /** remove GC collection guard if no further mark is set */ public extern(C) void unmarkMemoryFromD(void* ptr){ synchronized(sync){ size_t* count = ptr in memoryGuard; if(count && (--(*count) == 0)){ memoryGuard.remove(ptr); } } } /** remove GC collection guard */ public extern(C) void forceUnmarkMemoryFromD(void* ptr){ if(ptr in memoryGuard){ memoryGuard.remove(ptr); } } -----BEGIN PGP SIGNATURE----- iD8DBQFDFZl53w+/yD4P9tIRAqK2AKChSl/FSjwgOjP5F5gcW3I5/ssWMwCeO342 dJz9D0mYY7R86BkKKfwhtME= =/Yl4 -----END PGP SIGNATURE-----
Aug 31 2005
parent reply Carlos Santander <csantander619 gmail.com> writes:
Thomas Kühne escribió:
 Please try the code below - it seems to work on Linux and Windows.
 

I get exactly the same as before.
 If it isn't working properly compile with "-debug=StdioInit" and/or

With this, I get: /usr/bin/ld: Undefined symbols: __d_gnu_cbridge_init_stdio
 execute the sniplet below BEFORE calling
 loadPhobos.
 
 Thomas
 
 - --------------------------------------------
 private import gcc.gc_guess_stack;
 
 //
 // argv from C's: int main(int argc, char **argv)
 //
 extern(C) setStackOriginGuess(char **argv){
 	stackOriginGuess = &argv;
 }
 - --------------------------------------------
 

I suppose this is the sniplet you were referring to. With this, I get: /usr/bin/ld: Undefined symbols: __D3gcc14gc_guess_stack16stackOriginGuessPv -- Carlos Santander Bernal
Aug 31 2005
parent reply =?ISO-8859-1?Q?Thomas_K=FChne?= <thomas-dloop kuehne.cn> writes:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Carlos Santander schrieb:
 Thomas Kühne escribió:
 
 Please try the code below - it seems to work on Linux and Windows.

I get exactly the same as before.

I can think of three (more or less) likely possibilities: 1) your ram is messed up 2) malloc is buggy 3) someone is messing up the memory Let's find out who is at fault: - ----- gdb ./application [some license stuff] (gdb) set env DYLD_INSERT_LIBRARIES /usr/lib/libgmalloc.dylib (gdb) r [some crash] (gdb) bt - ----- further information: http://developer.apple.com/documentation/Darwin/Reference/ManPages/man3/libgmalloc.3.html Thomas -----BEGIN PGP SIGNATURE----- iD8DBQFDGLwJ3w+/yD4P9tIRAkmOAJwOfJAI6Ihyox2iH5NJsCaN8pElOACgqjoC XMrmksbwER++lR0gECEpjos= =qGCK -----END PGP SIGNATURE-----
Sep 02 2005
parent reply Carlos Santander <csantander619 gmail.com> writes:
Thomas Kühne escribió:
 
 [snip]
 
 I can think of three (more or less) likely possibilities:
 1) your ram is messed up
 2) malloc is buggy
 3) someone is messing up the memory
 
 Let's find out who is at fault:
 
 - -----
 
 gdb ./application
 [some license stuff]
 (gdb) set env DYLD_INSERT_LIBRARIES /usr/lib/libgmalloc.dylib
 (gdb) r
 [some crash]
 (gdb) bt
 
 - -----
 
 further information:
 http://developer.apple.com/documentation/Darwin/Reference/ManPages/man3/libgmalloc.3.html
 
 Thomas

I'm sorry, but I don't understand what you're trying to say here. I entered that "set env ..." command but the result was exactly the same. I'm lost by this post... -- Carlos Santander Bernal
Sep 02 2005
parent =?ISO-8859-1?Q?Thomas_K=FChne?= <thomas-dloop kuehne.cn> writes:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Carlos Santander schrieb:
 Thomas Kühne escribió:
 
 [snip]

 I can think of three (more or less) likely possibilities:
 1) your ram is messed up
 2) malloc is buggy
 3) someone is messing up the memory

 Let's find out who is at fault:

 - -----

 gdb ./application
 [some license stuff]
 (gdb) set env DYLD_INSERT_LIBRARIES /usr/lib/libgmalloc.dylib
 (gdb) r
 [some crash]
 (gdb) bt

 - -----

 further information:
 http://developer.apple.com/documentation/Darwin/Reference/ManPages/man3/libgmalloc.3.html


 Thomas

I'm sorry, but I don't understand what you're trying to say here. I entered that "set env ..." command but the result was exactly the same. I'm lost by this post...

First of all I assume: neither your RAM nor your kernel are broken Ok, let's have a look at the backtrace:
 Program received signal EXC_BAD_ACCESS, Could not access memory.
 0x9001f898 in malloc_create_zone ()
 (gdb) bt
 #0  0x9001f898 in malloc_create_zone ()
 #1  0x9002c424 in _malloc_initialize ()
 #2  0x90001a00 in malloc ()
 #3  0x000042e8 in gc_init () at
  ../../../gcc-3.4.3/libphobos/internal/gc/gc.d:106
 #4  0x00001958 in Dinit () at d.d:32
 #5  0x8fe1a278 in __dyld__dyld_start ()

Etnries #2 to #0 indicate, that the system call "malloc" exploded. Neither malloc_create_zone nor _malloc_initialize seem to be properly documented. As a side note http://developer.apple.com/documentation/Darwin/Reference/ManPages/man3/malloc.3.html states that malloc should return a NULL pointer if there were any error, but we aren't even getting to the return stage. So what does OpenDarwin do? http://darwinsource.opendarwin.org/10.2/Libc-262/gen/malloc.c
 void *malloc(size_t size) {
    return malloc_zone_malloc(inline_malloc_default_zone(), size);
 }

 static inline malloc_zone_t *inline_malloc_default_zone(void) {
    if (!malloc_num_zones) _malloc_initialize();
    return malloc_zones[0];
 }

 static void _malloc_initialize(void) {
    // guaranteed to be called only once
    (void)malloc_create_zone(0, 0);
    malloc_set_zone_name(malloc_zones[0], "DefaultMallocZone");
    LOCK_INIT(_malloc_lock);
 }

 malloc_zone_t *malloc_create_zone(vm_size_t start_size, unsigned
 flags) {
    malloc_zone_t	*zone;
    if (!malloc_num_zones) {
	char	**env = * _NSGetEnviron();
	char	**p;
	char	*c;
	/* Given that all environment variables start with "Malloc" we
	optimize by scanning quickly first the environment, therefore
	avoiding repeated calls to getenv() */
	for (p = env; (c = *p) != NULL; ++p) {
	    if (!strncmp(c, "Malloc", 6)) {
		set_flags_from_environment();
		break;
	    }
	}

    }
    zone = create_scalable_zone(start_size, malloc_debug_flags);
    malloc_zone_register(zone);
    return zone;
 }

Either the following line is the reason or somewhere code before gc.d:106 messed up malloc_zones or malloc_num_zones (e.g by writing past the allocated memory). char **env = * _NSGetEnviron(); Thomas -----BEGIN PGP SIGNATURE----- iD8DBQFDGU7N3w+/yD4P9tIRApZWAJ491tHKiVjeO0YivmyNtGpbYX2VBgCgh4zo /Y2cVvASUxrFTrCHvDgJFco= =OXXu -----END PGP SIGNATURE-----
Sep 03 2005