www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - extern (C) private linking issue

reply William R. DeVore <quartz13163 distanthumans.org> writes:
I am running into an issue under windows during linking.

I am getting an optlink error based on a private function in a module:

[quote]
C:\Working\D1.0\Derelict228\examples\graphical>build  simulation -full
Using Double Precision
OPTLINK (R) for Win32 Release 7.50B1
Copyright (C) Digital Mars 1989 - 2001 All Rights Reserved

Simulations\CylBoxSlide.obj(CylBoxSlide) Offset 01494H Record Type 00C3
Error 1: Previous Definition Different : _collisionCallback 
[/quote]

File CylVsSphere.d has:
[code]
extern (C) private void collisionCallback(void* data, dGeomID o1, dGeomID o2) {
...
} 
[/code]

and
CylBoxSlide.d has:
[code]
extern (C) private void collisionCallback(void* data, dGeomID o1, dGeomID o2) {
...
}
[/code]

Doesn't the private attribute hide the functions?

These modules are imported in a factory module (SimFactory.d) as so:
[code]
module Simulations.SimFactory;

import Simulations.ISimulation;
import Simulations.CylVsSphere;
import Simulations.CylBoxSlide;
...
[/code]

Linux linker respects the scope but window doesn't. I am using dmd 1.007

Any suggestions? Should I submit a bugzilla?
I really don't want to have a unique name for each collision callback function
inside a module if I can avoid it.

Thks.

-Will (Quartz) quartz13163 at distanthumans dot info
Feb 25 2007
parent reply Derek Parnell <derek nomail.afraid.org> writes:
On Sun, 25 Feb 2007 23:33:25 -0500, William R. DeVore wrote:

 I am running into an issue under windows during linking.
 
 I am getting an optlink error based on a private function in a module:
 
 [quote]
 C:\Working\D1.0\Derelict228\examples\graphical>build  simulation -full
 Using Double Precision
 OPTLINK (R) for Win32 Release 7.50B1
 Copyright (C) Digital Mars 1989 - 2001 All Rights Reserved
 
 Simulations\CylBoxSlide.obj(CylBoxSlide) Offset 01494H Record Type 00C3
 Error 1: Previous Definition Different : _collisionCallback 
 [/quote]
 
 File CylVsSphere.d has:
 [code]
 extern (C) private void collisionCallback(void* data, dGeomID o1, dGeomID o2) {
 ...
 } 
 [/code]
 
 and
 CylBoxSlide.d has:
 [code]
 extern (C) private void collisionCallback(void* data, dGeomID o1, dGeomID o2) {
 ...
 }
 [/code]
 
 Doesn't the private attribute hide the functions?
 
 These modules are imported in a factory module (SimFactory.d) as so:
 [code]
 module Simulations.SimFactory;
 
 import Simulations.ISimulation;
 import Simulations.CylVsSphere;
 import Simulations.CylBoxSlide;
 ...
 [/code]
 
 Linux linker respects the scope but window doesn't. I am using dmd 1.007
 
 Any suggestions? Should I submit a bugzilla?
 I really don't want to have a unique name for each collision callback function
inside a module if I can avoid it.

I'll have a go at this one, but I'm just guessing... The 'private' qualifier does "hide" is from the compiler's point of view. But it is not so much "hiding" as "preventing access". That is, the compiler will stop code in one module from trying to call a private function in another module. The "extern (C)" qualifier stops the compiler from mangling the name. Without this qualifier, the compiler adds the module name, and the argument signature to the name of a function in the object file. That means that two functions with the same name, but in different modules get different linkage names. However, by using "extern (C)" you override that so that each module's object file will contain the same linkage name. Why do you need to specify "extern (C)"? -- Derek (skype: derek.j.parnell) Melbourne, Australia "Justice for David Hicks!" 26/02/2007 4:21:48 PM
Feb 25 2007
parent reply Frits van Bommel <fvbommel REMwOVExCAPSs.nl> writes:
Derek Parnell wrote:
 On Sun, 25 Feb 2007 23:33:25 -0500, William R. DeVore wrote:
 
 I am running into an issue under windows during linking.

 I am getting an optlink error based on a private function in a module:


 Linux linker respects the scope but window doesn't. I am using dmd 1.007

 Any suggestions? Should I submit a bugzilla?
 I really don't want to have a unique name for each collision callback function
inside a module if I can avoid it.

I'll have a go at this one, but I'm just guessing... The 'private' qualifier does "hide" is from the compiler's point of view. But it is not so much "hiding" as "preventing access". That is, the compiler will stop code in one module from trying to call a private function in another module.

Pretty good guess ;).
 The "extern (C)" qualifier stops the compiler from mangling the name.
 Without this qualifier, the compiler adds the module name, and the argument
 signature to the name of a function in the object file. That means that two
 functions with the same name, but in different modules get different
 linkage names. However, by using "extern (C)" you override that so that
 each module's object file will contain the same linkage name. 
 
 Why do you need to specify "extern (C)"?

Seeing the word "callback" so often makes me think he probably uses these functions for use as a callback (function pointer) passed to a C API. So he needs them to use the C calling convention, which they will use when declared extern(C). I have also on occasion wanted to specify calling convention without specifying mangling, but current D doesn't offer that possibility :(.
Feb 26 2007
parent reply Will DeVore (Quartz) <quartz13163 distanthumans.org> writes:
Frits van Bommel Wrote:

I should have explained the environment a bit better, but Frits you are
correct. I am experiencing this using ODE.org. When a collision occurs ODE
calls back to the D code. The callback needs to be defined as extern (C)
otherwise D crashes when the callback completes.

I was using the 'private' attribute to in the module such that it wouldn't
clash with the other simulation modules that have the same function name.

 I have also on occasion wanted to specify calling convention without 
 specifying mangling, but current D doesn't offer that possibility :(.

I wonder why then it works under linux though. The linux linker seems to be able to identify the correct private function. I don't really know how Optlink works but I would say it is having problems making unique mangled names inside of modules with private attributes. Hmm...
Feb 26 2007
parent reply Frits van Bommel <fvbommel REMwOVExCAPSs.nl> writes:
Will DeVore (Quartz) wrote:
 I wonder why then it works under linux though. The linux linker seems to be
able to identify the correct private function.

It _doesn't_ work. Both functions are put in section .gnu.linkonce.ttext, which means the linker will throw away one of them and silently use the other in its place. In this case, I prefer Optlink behavior.
 I don't really know how Optlink works but I would say it is having 

attributes. Hmm... No, Optlink does exactly what it should do in this instance. _DMD_ has problems making unique mangled names of extern(C) functions. The main problem being that it's not allowed to do so :P. 'extern(C)' means it has to use the C mangling as well as the C calling convention, and C mangling means no mangling at all (except, on Windows, a leading '_' -- not much help).
Feb 26 2007
parent William R. DeVore <quartz13163 distanthumans.org> writes:
Frits van Bommel Wrote:

 It _doesn't_ work. Both functions are put in section 
 .gnu.linkonce.ttext, which means the linker will throw away one of them 
...

Thanks Frits for clearing that up for me. I didn't realize that was happening. :)
Feb 26 2007