Skip to content

Commit 044cf31

Browse files
committed
improve dynamic loading example
1 parent 8fbe178 commit 044cf31

File tree

3 files changed

+51
-9
lines changed

3 files changed

+51
-9
lines changed

doc/modules/ROOT/examples/CMakeLists.txt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ endif()
1717

1818
file(GLOB cpp_files "*.cpp")
1919

20-
foreach(cpp ${cpp_files})
20+
foreach (cpp ${cpp_files})
2121
cmake_path(REMOVE_EXTENSION cpp LAST_ONLY OUTPUT_VARIABLE stem)
2222
string(REGEX REPLACE ".*/" "" stem ${stem})
2323
add_executable(${stem} ${cpp})
@@ -27,4 +27,7 @@ foreach(cpp ${cpp_files})
2727
endforeach()
2828

2929
add_subdirectory(headers_namespaces)
30-
add_subdirectory(shared_libs)
30+
31+
if (NOT WIN32)
32+
add_subdirectory(shared_libs)
33+
endif()

doc/modules/ROOT/examples/shared_libs/CMakeLists.txt

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
# See accompanying file LICENSE_1_0.txt
44
# or copy at http://www.boost.org/LICENSE_1_0.txt)
55

6-
message(STATUS "Building dynamic_shared loading examples")
6+
message(STATUS "Building shared library examples")
7+
8+
add_compile_definitions(BOOST_OPENMETHOD_ENABLE_RUNTIME_CHECKS)
79

810
# ------------------------------------------------------------------------------
911
# static linking
@@ -23,7 +25,9 @@ add_executable(dynamic dynamic_main.cpp)
2325
set_target_properties(dynamic PROPERTIES ENABLE_EXPORTS ON)
2426
target_link_libraries(dynamic Boost::openmethod Boost::dll)
2527
add_dependencies(dynamic shared)
26-
add_test(NAME dynamic_shared COMMAND dynamic)
28+
if (NOT WIN32)
29+
add_test(NAME dynamic_shared COMMAND dynamic)
30+
endif()
2731

2832
# ------------------------------------------------------------------------------
2933
# dynamic loading, indirect virtual_ptrs
@@ -40,4 +44,6 @@ target_compile_definitions(
4044
set_target_properties(indirect PROPERTIES ENABLE_EXPORTS ON)
4145
target_link_libraries(indirect Boost::openmethod Boost::dll)
4246
add_dependencies(indirect indirect_shared)
43-
add_test(NAME indirect_shared COMMAND indirect)
47+
if (NOT WIN32)
48+
add_test(NAME indirect_shared COMMAND indirect)
49+
endif()

doc/modules/ROOT/pages/shared_libraries.adoc

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,39 @@ overriders provided by the shared library are removed from the method.
7777
include::{shared}/dynamic_main.cpp[tag=unload]
7878
----
7979

80+
### Windows
81+
82+
If we try this example on Windows, the result is disappointing:
83+
84+
```
85+
Before loading the shared library.
86+
cow meets wolf -> greet
87+
wolf meets cow -> greet
88+
89+
After loading the shared library.
90+
cow meets wolf -> greet
91+
wolf meets cow -> greet
92+
cow meets tiger -> unknown class struct Tiger
93+
```
94+
95+
What happens here is that the program and the DLL have their own copies of
96+
"global" variables. When the DLL is loaded, its static constructors run, and
97+
they add overriders to _their_ copy of the method (the `method::fn` static
98+
variable for the given name and signature). They are ignored when the main
99+
program calls `initialize`.
100+
101+
Likewise, `BOOST_OPENMETHOD_CLASSES(Tiger, Carnivore);` in the DLL adds `Tiger`
102+
to the DLL's copy of the registry. For the perspective of the program's
103+
registry, the class does not exist.
104+
105+
In theory, this can be fixed by adding `__declspec(dllimport)` and
106+
`__declspec(dllexport)` attributes where needed. However, this is not practical,
107+
because programs and DLLs can both import and export registries and methods. The
108+
underlying objects are instantiated from templates, which complicates the
109+
matter. Research is being done on this subject. However, as of now, dynamic
110+
loading is supported on Windows only if it does not attempt to share a registry
111+
across modules.
112+
80113
### Indirect Vptrs
81114

82115
`initialize` rebuilds the v-tables in the registry. This invalidates all the
@@ -87,10 +120,10 @@ their execution.
87120
88121
Otherwise, indirect v-table pointers must be used. This is achieved by using a
89122
registry that contains the cpp:indirect_vptr[] policy.
90-
`<boost/openmethod/default_registry.hpp>` provides an `indirect_registry` which
91-
has the same policies as `default_registry`, plus `indirect_vptr`. We can use it
92-
to override the default registry, for example using a compiler command-line
93-
switch (`-DBOOST_OPENMETHOD_DEFAULT_REGISTRY=indirect_registry`).
123+
`<boost/openmethod/default_registry.hpp>` provides an cpp:indirect_registry[]
124+
that has the same policies as `default_registry`, plus `indirect_vptr`. We can
125+
use it to override the default registry, for example using a compiler
126+
command-line switch (`-DBOOST_OPENMETHOD_DEFAULT_REGISTRY=indirect_registry`).
94127
95128
Here is an example of a program that carries `virtual_ptr`{empty}'s across
96129
`initialize` calls:

0 commit comments

Comments
 (0)