www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Calling D from C, C++, =?UTF-8?Q?Python=E2=80=A6?=

reply Russel Winder via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
Is there an easy way of knowing when you do not have to initialize the
D runtime system to call D code from, in this case, Python via a C
adapter?

I na=C3=AFvely transformed some C++ to D, without consideration of D runtim=
e
systems, compiled it and it all worked. Which is good, but=E2=80=A6

--=20
Russel.
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D
Dr Russel Winder      t: +44 20 7585 2200   voip: sip:russel.winder ekiga.n=
et
41 Buckmaster Road    m: +44 7770 465 077   xmpp: russel winder.org.uk
London SW11 1EN, UK   w: www.russel.org.uk  skype: russel_winder
Sep 10 2015
next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2015-09-10 20:01, Russel Winder via Digitalmars-d-learn wrote:
 Is there an easy way of knowing when you do not have to initialize the
 D runtime system to call D code from, in this case, Python via a C
 adapter?
You always need to initialize the D runtime, unless you have a D main function. You can initialize the runtime as many times you like, assuming you also deinitialize it the same number of times. -- /Jacob Carlborg
Sep 11 2015
parent reply Russel Winder via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
On Fri, 2015-09-11 at 21:50 +0200, Jacob Carlborg via Digitalmars-d
-learn wrote:
 On 2015-09-10 20:01, Russel Winder via Digitalmars-d-learn wrote:
 Is there an easy way of knowing when you do not have to initialize
 the
 D runtime system to call D code from, in this case, Python via a C
 adapter?
=20 You always need to initialize the D runtime, unless you have a D main function. You can initialize the runtime as many times you like,=20 assuming you also deinitialize it the same number of times.
I have a small D function (C linkage) compiled to a shared object that I am calling from Python via CFFI that works fine with no D runtime initialization. Thus I have experimental evidence "always" is not entirely the case! I really need to explore the boundaries of what point you have to actually initialize the D runtime=E2=80=A6 --=20 Russel. =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D Dr Russel Winder t: +44 20 7585 2200 voip: sip:russel.winder ekiga.n= et 41 Buckmaster Road m: +44 7770 465 077 xmpp: russel winder.org.uk London SW11 1EN, UK w: www.russel.org.uk skype: russel_winder
Sep 12 2015
parent reply Jacob Carlborg <doob me.com> writes:
On 2015-09-12 10:56, Russel Winder via Digitalmars-d-learn wrote:

 I have a small D function (C linkage) compiled to a shared object that
 I am calling from Python via CFFI that works fine with no D runtime
 initialization. Thus I have experimental evidence "always" is not
 entirely the case! I really need to explore the boundaries of what
 point you have to actually initialize the D runtime…
Well, if your D function doesn't use anything of the runtime I guess it's not necessary. Example: void foo () { printf("foo\n"); } -- /Jacob Carlborg
Sep 12 2015
parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Saturday, 12 September 2015 at 09:47:55 UTC, Jacob Carlborg 
wrote:
 Well, if your D function doesn't use anything of the runtime I 
 guess it's not necessary.
Right. If you don't call into the threading system in the druntime, you should be ok. Keep in mind though that the GC uses the threads.... and the new expression, array literals, array append, and others use the GC. Runtime.initialize is also what calls static and module constructors... and might have responsibility for fixing up dynamic casting of class objects in a shared lib too, I'm not sure about that. But if you avoid the bulk of the runtime functions, indeed you can get away without initializing it. Just that null thread handle is likely to cause segfaults in places where you might not expect if you don't. It is best to initialize it. Lots of C libraries need an init an teardown call, so surely the Python interop provides some solution for it. idk what it would be though.
Sep 12 2015
parent reply Brad Roberts via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
On 9/12/15 9:20 AM, Adam D. Ruppe via Digitalmars-d-learn wrote:
 On Saturday, 12 September 2015 at 09:47:55 UTC, Jacob Carlborg wrote:
 Well, if your D function doesn't use anything of the runtime I guess it's not
necessary.
Right. If you don't call into the threading system in the druntime, you should be ok. Keep in mind though that the GC uses the threads.... and the new expression, array literals, array append, and others use the GC. Runtime.initialize is also what calls static and module constructors... and might have responsibility for fixing up dynamic casting of class objects in a shared lib too, I'm not sure about that. But if you avoid the bulk of the runtime functions, indeed you can get away without initializing it. Just that null thread handle is likely to cause segfaults in places where you might not expect if you don't. It is best to initialize it. Lots of C libraries need an init an teardown call, so surely the Python interop provides some solution for it. idk what it would be though.
I think it's safest to say (and it belongs in the spec somewhere) that executing D code before initializing the runtime results in undefined behavior, or something along those lines. You can get away with it in some circumstances, but it's at your own risk.
Sep 12 2015
parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Saturday, 12 September 2015 at 18:20:37 UTC, Brad Roberts 
wrote:
 You can get away with it in some circumstances, but it's at 
 your own risk.
Yeah, I agree.
Sep 12 2015
prev sibling parent reply Jakob Ovrum <jakobovrum gmail.com> writes:
On Thursday, 10 September 2015 at 18:01:10 UTC, Russel Winder 
wrote:
 Is there an easy way of knowing when you do not have to 
 initialize the D runtime system to call D code from, in this 
 case, Python via a C adapter?

 I naïvely transformed some C++ to D, without consideration of D 
 runtime systems, compiled it and it all worked. Which is good, 
 but…
Surely the reasonable choice is to always initialize the runtime in a sensible location? What do you gain from not initializing it, and is it really worth the effort? core.runtime has Runtime.initialize and Runtime.terminate. In a Windows DLL, it's sensible to use DllMain to call these. core.sys.windows.dll.SimpleDllMain is a mixin template that makes it easy: version(Windows) { import core.sys.windows.dll; mixin SimpleDllMain; } On Linux and other ELF-using platforms, initialization and deinitialization functions could be placed in the .init and .deinit special sections, but I don't know if druntime has any convenient provisions for this. With GDC and LDC you can probably use a pragma to put functions in these sections, but I don't know if DMD has such a pragma. I don't know what the equivalent is for Apple's Mach-O shared libraries.
Sep 13 2015
next sibling parent Jakob Ovrum <jakobovrum gmail.com> writes:
On Sunday, 13 September 2015 at 10:10:32 UTC, Jakob Ovrum wrote:
 On Thursday, 10 September 2015 at 18:01:10 UTC, Russel Winder 
 wrote:
 Is there an easy way of knowing when you do not have to 
 initialize the D runtime system to call D code from, in this 
 case, Python via a C adapter?

 I naïvely transformed some C++ to D, without consideration of 
 D runtime systems, compiled it and it all worked. Which is 
 good, but…
Surely the reasonable choice is to always initialize the runtime in a sensible location? What do you gain from not initializing it, and is it really worth the effort? core.runtime has Runtime.initialize and Runtime.terminate. In a Windows DLL, it's sensible to use DllMain to call these. core.sys.windows.dll.SimpleDllMain is a mixin template that makes it easy: version(Windows) { import core.sys.windows.dll; mixin SimpleDllMain; } On Linux and other ELF-using platforms, initialization and deinitialization functions could be placed in the .init and .deinit special sections, but I don't know if druntime has any convenient provisions for this. With GDC and LDC you can probably use a pragma to put functions in these sections, but I don't know if DMD has such a pragma. I don't know what the equivalent is for Apple's Mach-O shared libraries.
Note that if the host program can call into the D shared library from multiple threads, it's necessary to register those threads with the runtime as well. The DllMain solution handles this automatically, but for other systems additional handling is necessary.
Sep 13 2015
prev sibling parent Jacob Carlborg <doob me.com> writes:
On 2015-09-13 12:10, Jakob Ovrum wrote:

 On Linux and other ELF-using platforms, initialization and
 deinitialization functions could be placed in the .init and .deinit
 special sections, but I don't know if druntime has any convenient
 provisions for this. With GDC and LDC you can probably use a pragma to
 put functions in these sections, but I don't know if DMD has such a pragma.

 I don't know what the equivalent is for Apple's Mach-O shared libraries.
It's supported in Mach-O as well, not sure about the section names though. -- /Jacob Carlborg
Sep 13 2015