Skip to content

Commit 66c863b

Browse files
authored
Add BABYLON_API calling convention macro for Core and Polyfills classes (#86)
Without explicit calling convention modifers, consumers are required to compile with the same calling convention used in the released binaries. If a consumer compiles with the `__stdcall` calling convention, the linker won't resolve the function calls because the released binaries are built with the default `__cdecl` calling convention. This change fixes the issue using an overridable `BABYLON_API` macro defined as `__cdecl` by default on Windows platforms or defined as empty on non-Windows platforms.
1 parent ef3bb85 commit 66c863b

File tree

27 files changed

+66
-35
lines changed

27 files changed

+66
-35
lines changed

Core/AppRuntime/Include/Babylon/AppRuntime.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ namespace Babylon
3535
void Dispatch(Dispatchable<void(Napi::Env)> callback);
3636

3737
// Default unhandled exception handler that outputs the error message to the program output.
38-
static void DefaultUnhandledExceptionHandler(const Napi::Error& error);
38+
static void BABYLON_API DefaultUnhandledExceptionHandler(const Napi::Error& error);
3939

4040
private:
4141
// These three methods are the mechanism by which platform- and JavaScript-specific

Core/AppRuntime/Source/AppRuntime_UWP.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
namespace Babylon
66
{
7-
void AppRuntime::DefaultUnhandledExceptionHandler(const Napi::Error& error)
7+
void BABYLON_API AppRuntime::DefaultUnhandledExceptionHandler(const Napi::Error& error)
88
{
99
std::ostringstream ss{};
1010
ss << "[Uncaught Error] " << error.Get("stack").As<Napi::String>().Utf8Value() << std::endl;

Core/AppRuntime/Source/AppRuntime_Win32.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
namespace Babylon
99
{
10-
void AppRuntime::DefaultUnhandledExceptionHandler(const Napi::Error& error)
10+
void BABYLON_API AppRuntime::DefaultUnhandledExceptionHandler(const Napi::Error& error)
1111
{
1212
std::ostringstream ss{};
1313
ss << "[Uncaught Error] " << error.Get("stack").As<Napi::String>().Utf8Value() << std::endl;

Core/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ else()
44
add_subdirectory(Node-API)
55
endif()
66

7+
add_subdirectory(Foundation)
78
add_subdirectory(JsRuntime)
89

910
if(JSRUNTIMEHOST_CORE_APPRUNTIME)

Core/Foundation/CMakeLists.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
set(SOURCES
2+
"Include/Babylon/Api.h")
3+
4+
add_library(Foundation INTERFACE)
5+
6+
target_include_directories(Foundation INTERFACE "Include")
7+
8+
set_property(TARGET Foundation PROPERTY FOLDER Core)
9+
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${SOURCES})
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#pragma once
2+
3+
#ifndef BABYLON_API
4+
#ifdef _WIN32
5+
#define BABYLON_API __cdecl
6+
#else
7+
#define BABYLON_API
8+
#endif
9+
#endif

Core/JsRuntime/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ target_include_directories(JsRuntime PRIVATE "Include/Babylon")
1010
target_include_directories(JsRuntime PUBLIC "Include")
1111

1212
target_link_libraries(JsRuntime
13+
PUBLIC Foundation
1314
PUBLIC napi
1415
PRIVATE arcana)
1516

Core/JsRuntime/Include/Babylon/JsRuntime.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#pragma once
22

33
#include <napi/env.h>
4+
#include <Babylon/Api.h>
45

56
#include <functional>
67
#include <mutex>
@@ -16,7 +17,7 @@ namespace Babylon
1617
static constexpr auto JS_NATIVE_NAME = "_native";
1718

1819
public:
19-
static Napi::Object GetFromJavaScript(Napi::Env env)
20+
static Napi::Object BABYLON_API GetFromJavaScript(Napi::Env env)
2021
{
2122
return env.Global().Get(JS_NATIVE_NAME).As<Napi::Object>();
2223
}
@@ -28,16 +29,16 @@ namespace Babylon
2829
// Any JavaScript errors that occur will bubble up as a Napi::Error C++ exception.
2930
// JsRuntime expects the provided dispatch function to handle this exception,
3031
// such as with a try/catch and logging the exception message.
31-
using DispatchFunctionT = std::function<void(std::function<void(Napi::Env)>)>;
32+
using DispatchFunctionT = std::function<void BABYLON_API (std::function<void BABYLON_API (Napi::Env)>)>;
3233

3334
// Note: It is the contract of JsRuntime that its dispatch function must be usable
3435
// at the moment of construction. JsRuntime cannot be built with dispatch function
3536
// that captures a reference to a not-yet-completed object that will be completed
3637
// later -- an instance of an inheriting type, for example. The dispatch function
3738
// must be safely callable as soon as it is passed to the JsRuntime constructor.
38-
static JsRuntime& CreateForJavaScript(Napi::Env, DispatchFunctionT);
39-
static JsRuntime& GetFromJavaScript(Napi::Env);
40-
void Dispatch(std::function<void(Napi::Env)>);
39+
static JsRuntime& BABYLON_API CreateForJavaScript(Napi::Env, DispatchFunctionT);
40+
static JsRuntime& BABYLON_API GetFromJavaScript(Napi::Env);
41+
void Dispatch(std::function<void BABYLON_API (Napi::Env)>);
4142

4243
protected:
4344
JsRuntime(const JsRuntime&) = delete;

Core/JsRuntime/Source/JsRuntime.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,13 @@ namespace Babylon
2525
jsNative.Set(JS_RUNTIME_NAME, jsRuntime);
2626
}
2727

28-
JsRuntime& JsRuntime::CreateForJavaScript(Napi::Env env, DispatchFunctionT dispatchFunction)
28+
JsRuntime& BABYLON_API JsRuntime::CreateForJavaScript(Napi::Env env, DispatchFunctionT dispatchFunction)
2929
{
3030
auto* runtime = new JsRuntime(env, std::move(dispatchFunction));
3131
return *runtime;
3232
}
3333

34-
JsRuntime& JsRuntime::GetFromJavaScript(Napi::Env env)
34+
JsRuntime& BABYLON_API JsRuntime::GetFromJavaScript(Napi::Env env)
3535
{
3636
return *NativeObject::GetFromJavaScript(env)
3737
.As<Napi::Object>()
@@ -40,7 +40,7 @@ namespace Babylon
4040
.Data();
4141
}
4242

43-
void JsRuntime::Dispatch(std::function<void(Napi::Env)> function)
43+
void JsRuntime::Dispatch(std::function<void BABYLON_API (Napi::Env)> function)
4444
{
4545
std::scoped_lock lock{m_mutex};
4646
m_dispatchFunction([function = std::move(function)](Napi::Env env) {

Core/Node-API/Include/Shared/napi/napi-inl.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ namespace details {
3333
constexpr int napi_no_external_buffers_allowed = 22;
3434

3535
template <typename FreeType>
36-
inline void default_finalizer(napi_env /*env*/, void* data, void* /*hint*/) {
36+
inline void NAPI_CDECL default_finalizer(napi_env /*env*/, void* data, void* /*hint*/) {
3737
delete static_cast<FreeType*>(data);
3838
}
3939

@@ -105,7 +105,7 @@ inline void WrapVoidCallback(Callable callback) {
105105

106106
template <typename Callable, typename Return>
107107
struct CallbackData {
108-
static inline napi_value Wrapper(napi_env env, napi_callback_info info) {
108+
static inline napi_value NAPI_CDECL Wrapper(napi_env env, napi_callback_info info) {
109109
return details::WrapCallback([&] {
110110
CallbackInfo callbackInfo(env, info);
111111
CallbackData* callbackData =
@@ -121,7 +121,7 @@ struct CallbackData {
121121

122122
template <typename Callable>
123123
struct CallbackData<Callable, void> {
124-
static inline napi_value Wrapper(napi_env env, napi_callback_info info) {
124+
static inline napi_value NAPI_CDECL Wrapper(napi_env env, napi_callback_info info) {
125125
return details::WrapCallback([&] {
126126
CallbackInfo callbackInfo(env, info);
127127
CallbackData* callbackData =
@@ -179,7 +179,7 @@ napi_value TemplatedInstanceVoidCallback(napi_env env, napi_callback_info info)
179179

180180
template <typename T, typename Finalizer, typename Hint = void>
181181
struct FinalizeData {
182-
static inline void Wrapper(napi_env env,
182+
static inline void NAPI_CDECL Wrapper(napi_env env,
183183
void* data,
184184
void* finalizeHint) NAPI_NOEXCEPT {
185185
WrapVoidCallback([&] {
@@ -209,7 +209,7 @@ template <typename ContextType = void,
209209
typename Finalizer = std::function<void(Env, void*, ContextType*)>,
210210
typename FinalizerDataType = void>
211211
struct ThreadSafeFinalize {
212-
static inline void Wrapper(napi_env env,
212+
static inline void NAPI_CDECL Wrapper(napi_env env,
213213
void* rawFinalizeData,
214214
void* /* rawContext */) {
215215
if (rawFinalizeData == nullptr) return;

0 commit comments

Comments
 (0)