Skip to content

Commit 2fcfa9f

Browse files
committed
fix passing struct as reference
1 parent 3e323e0 commit 2fcfa9f

File tree

3 files changed

+46
-22
lines changed

3 files changed

+46
-22
lines changed

NativeScript/ffi/Struct.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ class StructObject {
5050
static napi_value fromNative(napi_env env, StructInfo* info, void* data,
5151
bool owned);
5252

53+
static bool isInstance(napi_env env, napi_value object);
54+
5355
~StructObject();
5456
};
5557

NativeScript/ffi/Struct.mm

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,15 @@ void StructObject_finalize(napi_env env, void* data, void* hint) {
356356
return result;
357357
}
358358

359+
bool StructObject::isInstance(napi_env env, napi_value object) {
360+
napi_value sizeofSymbol = jsSymbolFor(env, "sizeof");
361+
napi_value prop;
362+
if (napi_get_property(env, object, sizeofSymbol, &prop) == napi_ok) {
363+
return true;
364+
}
365+
return false;
366+
}
367+
359368
napi_value StructObject::getJSClass(napi_env env, StructInfo* info) {
360369
if (info->jsClass != nullptr) {
361370
return get_ref_value(env, info->jsClass);

NativeScript/ffi/TypeConv.mm

Lines changed: 35 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "MetadataReader.h"
99
#include "ObjCBridge.h"
1010
#include "ffi.h"
11+
#include "ffi/Struct.h"
1112
#include "js_native_api.h"
1213
#include "js_native_api_types.h"
1314
#include "node_api_util.h"
@@ -18,9 +19,9 @@
1819
#include <stdbool.h>
1920
#include <memory>
2021
#include <string>
21-
#include <vector>
22-
#include <unordered_set>
2322
#include <unordered_map>
23+
#include <unordered_set>
24+
#include <vector>
2425

2526
namespace nativescript {
2627

@@ -44,7 +45,7 @@
4445
ffi_type* typeFromStruct(napi_env env, const char** encoding) {
4546
// Extract struct name for cycle detection
4647
std::string structname;
47-
const char* nameStart = *encoding + 1; // skip '{'
48+
const char* nameStart = *encoding + 1; // skip '{'
4849
const char* c = nameStart;
4950
while (*c != '=') {
5051
structname += *c;
@@ -59,17 +60,17 @@
5960
forwardType->size = 0;
6061
forwardType->alignment = 0;
6162
forwardType->elements = nullptr;
62-
63+
6364
// Cache this forward declaration for later resolution
6465
forwardDeclaredEncodingStructs[structname] = forwardType;
65-
66+
6667
// Skip the struct encoding
6768
(*encoding)++; // skip '{'
6869
while (**encoding != '}') {
6970
(*encoding)++;
7071
}
7172
(*encoding)++; // skip '}'
72-
73+
7374
return forwardType;
7475
}
7576

@@ -82,7 +83,7 @@
8283
(*encoding)++;
8384
}
8485
(*encoding)++; // skip '}'
85-
86+
8687
return forwardIt->second;
8788
}
8889

@@ -126,7 +127,7 @@
126127
forwardType->size = type->size;
127128
forwardType->alignment = type->alignment;
128129
forwardType->elements = type->elements;
129-
130+
130131
// Clean up the temporary type and use the forward declaration
131132
delete type;
132133
type = forwardType;
@@ -149,7 +150,7 @@
149150
forwardType->size = 0;
150151
forwardType->alignment = 0;
151152
forwardType->elements = nullptr;
152-
153+
153154
// Cache this forward declaration for later resolution
154155
forwardDeclaredStructs[structOffset] = forwardType;
155156
return forwardType;
@@ -174,7 +175,7 @@
174175
auto name = reader->resolveString(nameOffset);
175176
bool next = true;
176177
MDSectionOffset currentOffset = structOffset + sizeof(MDSectionOffset); // skip name
177-
currentOffset += sizeof(uint16_t); // skip size
178+
currentOffset += sizeof(uint16_t); // skip size
178179

179180
std::vector<ffi_type*> elements;
180181

@@ -205,7 +206,7 @@
205206
forwardType->size = type->size;
206207
forwardType->alignment = type->alignment;
207208
forwardType->elements = type->elements;
208-
209+
209210
// Clean up the temporary type and use the forward declaration
210211
delete type;
211212
type = forwardType;
@@ -583,6 +584,9 @@ void toNative(napi_env env, napi_value value, void* result, bool* shouldFree,
583584
double val;
584585
napi_coerce_to_number(env, value, &value);
585586
napi_get_value_double(env, value, &val);
587+
if (std::isnan(val) || std::isinf(val)) {
588+
val = 0.0;
589+
}
586590
*(double*)result = val;
587591
}
588592

@@ -723,6 +727,15 @@ void toNative(napi_env env, napi_value value, void* result, bool* shouldFree,
723727
return;
724728
}
725729

730+
if (StructObject::isInstance(env, value)) {
731+
StructObject* structObj = StructObject::unwrap(env, value);
732+
if (structObj != nullptr) {
733+
*res = structObj->data;
734+
} else
735+
*res = nullptr;
736+
return;
737+
}
738+
726739
void* wrapped;
727740
status = napi_unwrap(env, value, &wrapped);
728741
if (status == napi_ok) {
@@ -957,7 +970,7 @@ void toNative(napi_env env, napi_value value, void* result, bool* shouldFree,
957970
StringTypeConv() { type = &ffi_type_pointer; }
958971

959972
napi_value toJS(napi_env env, void* cont, uint32_t flags) override {
960-
void *value = *((void**)cont);
973+
void* value = *((void**)cont);
961974
napi_value result;
962975
napi_create_string_utf8(env, (char*)value, NAPI_AUTO_LENGTH, &result);
963976
return result;
@@ -1677,23 +1690,23 @@ void toNative(napi_env env, napi_value value, void* result, bool* shouldFree,
16771690
structname += *c;
16781691
c++;
16791692
}
1680-
1693+
16811694
// Check if we already have a cached StructTypeConv for this encoding-based struct
16821695
auto cacheIt = encodingStructCache.find(structname);
16831696
if (cacheIt != encodingStructCache.end()) {
16841697
return cacheIt->second;
16851698
}
1686-
1699+
16871700
auto bridgeState = ObjCBridgeState::InstanceData(env);
16881701
// NSLog(@"struct: %s, %d", structname.c_str(),
16891702
// bridgeState->structOffsets[structname]);
16901703
auto structOffset = bridgeState->structOffsets[structname];
16911704
auto type = typeFromStruct(env, encoding);
16921705
auto structTypeConv = std::make_shared<StructTypeConv>(StructTypeConv(structOffset, type));
1693-
1706+
16941707
// Cache the StructTypeConv
16951708
encodingStructCache[structname] = structTypeConv;
1696-
1709+
16971710
return structTypeConv;
16981711
}
16991712
case 'b': {
@@ -1865,26 +1878,26 @@ void toNative(napi_env env, napi_value value, void* result, bool* shouldFree,
18651878
}
18661879
structOffset += isUnion ? reader->unionsOffset : reader->structsOffset;
18671880
auto structName = reader->getString(structOffset);
1868-
1881+
18691882
// Check if we already have a cached StructTypeConv for this struct
18701883
auto cacheIt = structTypeCache.find(structOffset);
18711884
if (cacheIt != structTypeCache.end()) {
18721885
return cacheIt->second;
18731886
}
1874-
1887+
18751888
// Check if we're currently processing this struct (recursion detection)
18761889
bool isRecursive = processingStructs.find(structOffset) != processingStructs.end();
1877-
1890+
18781891
ffi_type* type = nullptr;
18791892
if (opaquePointers != 2 && !isRecursive) {
18801893
type = typeFromStruct(env, reader, structOffset, isUnion);
18811894
}
1882-
1895+
18831896
auto structTypeConv = std::make_shared<StructTypeConv>(structOffset, type);
1884-
1897+
18851898
// Cache the StructTypeConv to handle recursion and avoid duplicates
18861899
structTypeCache[structOffset] = structTypeConv;
1887-
1900+
18881901
return structTypeConv;
18891902
}
18901903

0 commit comments

Comments
 (0)