Thread overview
extern (C) private linking issue
Feb 26, 2007
William R. DeVore
Feb 26, 2007
Derek Parnell
Feb 26, 2007
Frits van Bommel
Feb 26, 2007
Frits van Bommel
Feb 27, 2007
William R. DeVore
February 26, 2007
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
February 26, 2007
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
February 26, 2007
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:
>>
[snip]
>>
>> 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 :(.
February 26, 2007
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...

February 26, 2007
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 problems making unique mangled names inside of modules with private 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).
February 27, 2007
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. :)