Skip to content

Shared (dynamic) OSI library on Windows: missing dllexport for protobuf data symbols #7

@jdsika

Description

@jdsika

Problem

The shared library target open_simulation_interface (SHARED at CMakeLists.txt L122) cannot be used on Windows (MSVC) because protobuf-generated C++ code does not emit __declspec(dllexport) for global data symbols such as _default_instance_ and descriptor tables.

Observed behavior

When a consumer links against open_simulation_interface.dll, the MSVC linker reports unresolved externals for every protobuf data symbol:

LNK2019: unresolved external symbol "class osi3::SensorView const osi3::_SensorView_default_instance_"

Setting WINDOWS_EXPORT_ALL_SYMBOLS ON on the shared target (as done by asam-osi-utilities) only exports functions — it does not export global data objects. This is a known MSVC limitation.

The osi-cpp documentation itself marks Windows dynamic linking as "NOT RECOMMENDED" with a reference to this protobuf discussion.

Evidence that it is solvable

dSPACE ships pre-built shared OSI libraries for Windows (import .lib + .dll) for their VEOS and SCALEXIO platforms, proving that the dllexport problem has a practical solution.

Proposed fix

Use protoc's dllexport_decl option so that all generated C++ code emits __declspec(dllexport) / __declspec(dllimport) annotations for both functions and data symbols.

1. Define an export macro

Create a header (e.g. osi_export.h):

`cpp
#pragma once

#if defined(_WIN32) || defined(_WIN64)
#ifdef OSI_BUILDING_SHARED
#define OSI_EXPORT __declspec(dllexport)
#else
#define OSI_EXPORT __declspec(dllimport)
#endif
#else
#define OSI_EXPORT attribute((visibility("default")))
#endif
`

2. Pass dllexport_decl to protoc

Replace the current protobuf_generate_cpp call (L73) with a custom protoc invocation that passes:

--cpp_out=dllexport_decl=OSI_EXPORT:<output_dir>

This makes every generated .pb.h wrap exported symbols with OSI_EXPORT.

3. Set the build-time define on the shared target

cmake target_compile_definitions(open_simulation_interface PRIVATE OSI_BUILDING_SHARED)

Consumers that link the import .lib will get __declspec(dllimport) automatically (the default when OSI_BUILDING_SHARED is not defined).

4. Update documentation

Remove or qualify the "NOT RECOMMENDED" note in setting_up_osi_cpp.adoc to explain that with dllexport_decl, Windows shared linking is fully supported.

Impact

  • Enables shared OSI on Windows — required for plugin architectures where multiple DLLs in the same process share a single OSI/protobuf runtime
  • Eliminates duplicate protobuf descriptor pool crashes caused by static linking into multiple DLLs
  • Aligns with what dSPACE already ships commercially
  • No impact on static builds (_static / _pic targets unchanged)

References

Metadata

Metadata

Assignees

Labels

help wantedExtra attention is neededquestionFurther information is requested

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions