LoadError: Double registration for method
peremato opened this issue · 14 comments
With this configuration I am getting following the error at module loading time:
ulia> using Geant4
[ Info: Precompiling Geant4 [559df036-b7a0-42fd-85df-7d5dd9d70f44]
Warning: Type 8G4String already had a mapped type set as G4StringAllocated using hash 5238750270 and const-ref indicator 0
ERROR: LoadError: Double registration for method (:function, :copy, :Base, 0x9df832de6d2b232b)
Somehow CxxWrap
thinks the method or type is defined twice, but I do not see it in the generated code.
Any idea of this this could be? When I tried yesterday it was somehow working.
Hello Pere,
I cannot reproduce the issue, because it fails before with the following error:
/home/opt/lib/libG4geometry.so: cannot allocate memory in static TLS block
Philippe.
I guess the problem is a missing compilation/linking flag such as
CXXFLAGS += -ftls-model=initial-exec -pthread
But the easiest is to use CMake to build the wrapper library instead of a hand-made Makefile. This is what I am using currently CMakeLists.txt
More info. The problem appears when I add G4Box.hh and G4UBox.hh to the list of headers. This explains why I was not getting this error yesterday.
input = [ "Geant4Wrap.h",
"G4RunManager.hh",
"G4NistManager.hh",
"G4LogicalVolume.hh",
"G4PVPlacement.hh",
"G4Box.hh",
"G4UBox.hh" ]
Hello Pere,
Neither adding the compilation flag or using cmake to build fixed the issue I had. Nevertheless, I've managed to circumvent it by setting the environment variable LD_PRELOAD
as:
LD_PRELOAD=/home/opt/lib/libG4geometry.so:/home/opt/lib/libG4digits_hits.so:/home/opt/lib/libG4processes.so
Back to your issue, the problem comes from a typedef/alias in G4VSolid.hh
:
using G4GeometryType = G4String;
Typedefs are not handled properly by wrapit. We still need to define how to do it. Current code makes a wrapper for the typedefs, but CxxWrap does not accept to have more than one wrapper for a type or one of its aliases. So it works only if the type is used uniformly with the same alias.
Two options to solve your issue, until I implement a clean handling of typedefs:
- Disabling
typedef
wrapping by commenting out the line#define WRAP_TYPEDEFS
insrc/CodeTree.cpp
; - or adding
G4GeometryType
in your veto file.
After fixing this, I have an error message about a CLHEP
class. I expect this can be solved by adding a CLHEP header in the extra_headers but I've not investigated it more.
Philippe.
Thanks for looking into it. I did check the diff of the generated wrapper code between working and not working I didn't realize that the culprit was the wrapper for G4GeometryType
.
What is the logic of generating the wrapper for the typesdefs if at the end is replaced by the actual type. Put it in another way, if a have a method/function returning a G4GeometryType
, it will actually return a G4String
for which we have the wrapper and CxxWrap knows about it. So, the typedef should be complete invisible, isn't it?
The function wrapper will actually return a G4GeometryType
.
One solution would indeed be to resolve all typedefs to the underlying type. The drawbacks are that, first, the underlying type can be complex, in particular for templated types (take as example std::string), second, the function signature of the Julia binding will differ from the original one.
I do not think is true. In my case it returns a G4String
or subclass of it.
box = G4Box("Box1", 1,2,3)
@test typeof(GetEntityType(box)) == Geant4.G4StringAllocated
@test typeof(GetEntityType(box)) <: G4String # Test Passed
@grasph What is needed for typedefs
(at least in my use case) is the following:
- Do not generate the wrapper for the typedef since it does not make sense because is an empty type with no methods. I have achieved this by adding the type to the veto file
- Make sure that the real types are selected by adding their header files as input to
wrapit
- Add in the Julia module the following lines:
I have done this step by hand, but it could be done with
const G4RotationMatrix = CLHEP!HepRotation const G4ThreeVector = CLHEP!Hep3Vector export G4ThreeVector, G4RotationMatrix
wrapit
I guess.
With these changes I am able to create G4ThreeVector
s and operate on them.
julia> box = G4Box("Box1", 1,2,3)
Geant4.G4BoxAllocated(Ptr{Nothing} @0x00007f9d136199f0)
julia> m1, m2 = G4ThreeVector(), G4ThreeVector()
(Geant4.CLHEP!Hep3VectorAllocated(Ptr{Nothing} @0x00007f9d0d4f6ca0), Geant4.CLHEP!Hep3VectorAllocated(Ptr{Nothing} @0x00007f9d10d27ea0))
julia> BoundingLimits(box, m1, m2)
julia> @test m1 == G4ThreeVector(-1,-2,-3)
Test Passed
julia> @test m2 == G4ThreeVector(1,2,3)
Test Passed
julia> @test m1 + m2 == G4ThreeVector()
Test Passed
OK. Thanks for the feedback. The typedef is useful for the ex002-ROOT example. It's a special case. It's for FILE which is a typedef to a struct which is declared in the system header, but not defined
I agree with you that wrapper to typedef should not be produced and another approach should be taken for the FILE use case (or it should be produced only in absence of wrapper for the underlying type).
The Julia aliases are needed for convenience only. You could also use Geant4.CLHEP!Hep3Vector
. Am I correct?
Philippe.
The Julia aliases are needed for convenience only. You could also use Geant4.CLHEP!Hep3Vector. Am I correct?
Yes, you can use Geant4.CLHEP!Hep3Vector
but will diverge from the C++ way of naming and showing the implementation choices.
Workaround is working fine
Some followup:
- This commit removes the typedef wrapper generation while solving use cases that depended on it.
- Automatic generation of julia type aliases to reflect c++ typedef/using statements is put on the TODO list. The list contains items with higher priority, like proper support of templates and splitting the generated code in smaller source files.
@grasph With these changes I get runtime problems on static variables. For example I get the error:
ERROR: LoadError: UndefVarError: CLHEP!HepRotation!IDENTITY not defined
Stacktrace:
[1] getproperty(x::Module, f::Symbol)
The generated wrapper being:
// defined in /Users/Shared/cvmfs/sft.cern.ch/lcg/views/LCG_102/x86_64-centos7-gcc11-opt/include/CLHEP/Vector/Rotation.h:368:28
types.method("CLHEP!HepRotation!IDENTITY", []()-> const CLHEP::HepRotation& { return CLHEP::HepRotation::IDENTITY; });
end the definition in C++ is:
368 static const HepRotation IDENTITY;