Skip to content

Commit f6024a5

Browse files
committed
feat: retType support string
1 parent 8c0e6ef commit f6024a5

File tree

12 files changed

+145
-103
lines changed

12 files changed

+145
-103
lines changed

dart_native/ios/Classes/DNBlockWrapper.m

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,9 @@ - (void)dealloc {
148148
ffi_closure_free(_closure);
149149
free(_descriptor);
150150
for (int i = 0; i < _numberOfArguments; i++) {
151-
free((void *)_typeEncodings[i]);
151+
if (*_typeEncodings[i] == '{') {
152+
free((void *)_typeEncodings[i]);
153+
}
152154
}
153155
free(_typeEncodings);
154156
NotifyDeallocToDart(_sequence, _dartPort);
@@ -280,16 +282,7 @@ - (NSString *)_parseTypeNames:(NSString *)typeNames
280282
}
281283
}
282284

283-
const char *encodeSource = encode.UTF8String;
284-
size_t typeLength = strlen(encodeSource) + 1;
285-
size_t size = sizeof(char) * typeLength;
286-
char *typePtr = (char *)malloc(size);
287-
if (typePtr == NULL) {
288-
DN_ERROR(DNCreateTypeEncodingError, @"malloc for type encoding fail: %s", encodeSource);
289-
return nil;
290-
}
291-
strlcpy(typePtr, encode.UTF8String, typeLength);
292-
self.typeEncodings[i] = typePtr;
285+
self.typeEncodings[i] = native_type_encoding(encode.UTF8String);
293286

294287
int length = DNTypeLengthWithTypeName(typeStr);
295288

dart_native/ios/Classes/DNMethodIMP.m

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,8 +167,8 @@ static void DNFFIIMPClosureFunc(ffi_cif *cif, void *ret, void **args, void *user
167167
args[i + indexOffset] = temp;
168168
}
169169
}
170-
171-
const char **types = native_types_encoding(methodIMP.typeEncoding, NULL, 0);
170+
int typesCount = 0;
171+
const char **types = native_types_encoding(methodIMP.typeEncoding, &typesCount, 0);
172172
if (!types) {
173173
return;
174174
}
@@ -190,6 +190,11 @@ static void DNFFIIMPClosureFunc(ffi_cif *cif, void *ret, void **args, void *user
190190
[invocation retainArguments];
191191
NotifyMethodPerformToDart(invocation, methodIMP, numberOfArguments, types);
192192
}
193+
for (int i = 0; i < typesCount; i++) {
194+
if (*types[i] == '{') {
195+
free((void *)types[i]);
196+
}
197+
}
193198
free(types);
194199
retObjectAddr = (int64_t)*(void **)retAddr;
195200
DNHandleReturnValue(ret, methodIMP, invocation);

dart_native/ios/Classes/DNObjectDealloc.m

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,19 +62,19 @@ - (instancetype)initWithHost:(NSObject *)host
6262
if (self) {
6363
_host = host;
6464
_hostAddress = (int64_t)host;
65-
if ([host isKindOfClass:NSClassFromString(@"Fuck")]) {
66-
fuxk = _hostAddress;
67-
}
65+
// if ([host isKindOfClass:NSClassFromString(@"Fuck")]) {
66+
// fuxk = _hostAddress;
67+
// }
6868
_dartPort = dartPort;
6969
objc_setAssociatedObject(host, _cmd, self, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
7070
}
7171
return self;
7272
}
7373

7474
- (void)dealloc {
75-
if (_hostAddress == fuxk) {
76-
77-
}
75+
// if (_hostAddress == fuxk) {
76+
//
77+
// }
7878
NotifyDeallocToDart(_hostAddress, _dartPort);
7979
}
8080

dart_native/ios/Classes/native_runtime.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ DN_EXTERN NSMethodSignature * _Nullable
2222
native_method_signature(Class cls, SEL selector);
2323

2424
DN_EXTERN void
25-
native_signature_encoding_list(NSMethodSignature *signature, const char * _Nonnull * _Nonnull typeEncodings);
25+
native_signature_encoding_list(NSMethodSignature *signature, const char * _Nonnull * _Nonnull typeEncodings, BOOL decodeRetVal);
2626

2727
DN_EXTERN BOOL
2828
native_add_method(id target, SEL selector, char *types, void *callback, Dart_Port dartPort);
@@ -41,15 +41,16 @@ native_get_class(const char *className, Class superclass);
4141
/// @param queue dispatch queue for async method.
4242
/// @param args arguments passed to method.
4343
/// @param dartPort port for dart isolate.
44-
/// @param stringTypeBitmaskPtr bitmask for checking if an argument is a string.
44+
/// @param stringTypeBitmask bitmask for checking if an argument is a string.
45+
/// @param retType type of return value.
4546
DN_EXTERN void * _Nullable
46-
native_instance_invoke(id object, SEL selector, NSMethodSignature *signature, dispatch_queue_t queue, void * _Nonnull * _Nullable args, void (^callback)(void *), Dart_Port dartPort, int64_t *stringTypeBitmaskPtr);
47+
native_instance_invoke(id object, SEL selector, NSMethodSignature *signature, dispatch_queue_t queue, void * _Nonnull * _Nullable args, void (^callback)(void *), Dart_Port dartPort, int64_t stringTypeBitmask, const char *_Nonnull *_Nonnull retType);
4748

4849
DN_EXTERN void *
4950
native_block_create(char *types, void *callback, Dart_Port dartPort);
5051

5152
DN_EXTERN void *
52-
native_block_invoke(void *block, void * _Nonnull * _Nullable args, Dart_Port dartPort, int64_t *stringTypeBitmaskPtr);
53+
native_block_invoke(void *block, void * _Nonnull * _Nullable args, Dart_Port dartPort, int64_t stringTypeBitmask);
5354

5455
DN_EXTERN const char * _Nonnull * _Nonnull
5556
native_all_type_encodings(void);

dart_native/ios/Classes/native_runtime.mm

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,18 @@
3232
}
3333

3434
void
35-
native_signature_encoding_list(NSMethodSignature *signature, const char **typeEncodings) {
35+
native_signature_encoding_list(NSMethodSignature *signature, const char **typeEncodings, BOOL decodeRetVal) {
3636
if (!signature || !typeEncodings) {
3737
return;
3838
}
3939

4040
for (NSUInteger i = 2; i < signature.numberOfArguments; i++) {
41-
*(typeEncodings + i - 1) = [signature getArgumentTypeAtIndex:i];
41+
const char *type = [signature getArgumentTypeAtIndex:i];
42+
*(typeEncodings + i - 1) = native_type_encoding(type);
43+
}
44+
if (decodeRetVal) {
45+
*typeEncodings = native_type_encoding(signature.methodReturnType);
4246
}
43-
*typeEncodings = signature.methodReturnType;
4447
}
4548

4649
BOOL
@@ -104,7 +107,7 @@
104107
}
105108

106109
void
107-
_fillArgsToInvocation(NSMethodSignature *signature, void **args, NSInvocation *invocation, NSUInteger offset, int64_t *stringTypeBitmaskPtr, NSMutableArray<NSString *> *stringTypeBucket) {
110+
_fillArgsToInvocation(NSMethodSignature *signature, void **args, NSInvocation *invocation, NSUInteger offset, int64_t stringTypeBitmask, NSMutableArray<NSString *> *stringTypeBucket) {
108111
for (NSUInteger i = offset; i < signature.numberOfArguments; i++) {
109112
const char *argType = [signature getArgumentTypeAtIndex:i];
110113
NSUInteger argsIndex = i - offset;
@@ -119,7 +122,7 @@
119122
// Already put struct in pointer on Dart side.
120123
[invocation setArgument:args[argsIndex] atIndex:i];
121124
} else if (argType[0] == '@' &&
122-
(*stringTypeBitmaskPtr >> (argsIndex + 1) & 0x1) == 1) {
125+
(stringTypeBitmask >> argsIndex & 0x1) == 1) {
123126
const unichar *data = ((const unichar **)args)[argsIndex];
124127
// First four uint16_t is for data length.
125128
const NSUInteger lengthDataSize = 4;
@@ -141,10 +144,10 @@
141144

142145
/// Return data for NSString: [--dataLength(64bit--)][--dataContent(utf16 without BOM)--]
143146
/// @param retVal origin return value
144-
/// @param stringTypeBitmaskPtr pointer to bitmask
145-
void *_dataForNSStringReturnValue(NSString *retVal, int64_t *stringTypeBitmaskPtr) {
147+
/// @param retType type for return value
148+
void *_dataForNSStringReturnValue(NSString *retVal, const char **retType) {
146149
// first bit is for return value.
147-
*stringTypeBitmaskPtr |= 0x1;
150+
*retType = native_all_type_encodings()[18];
148151
NSUInteger length = 0;
149152
const uint16_t *utf16BufferPtr = native_convert_nsstring_to_utf16(retVal, &length);
150153
size_t size = sizeof(uint16_t) * length;
@@ -163,15 +166,15 @@
163166
}
164167

165168
void *
166-
native_instance_invoke(id object, SEL selector, NSMethodSignature *signature, dispatch_queue_t queue, void **args, void (^callback)(void *), Dart_Port dartPort, int64_t *stringTypeBitmaskPtr) {
167-
if (!object || !selector || !signature || !stringTypeBitmaskPtr) {
169+
native_instance_invoke(id object, SEL selector, NSMethodSignature *signature, dispatch_queue_t queue, void **args, void (^callback)(void *), Dart_Port dartPort, int64_t stringTypeBitmask, const char **retType) {
170+
if (!object || !selector || !signature) {
168171
return NULL;
169172
}
170173
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
171174
invocation.target = object;
172175
invocation.selector = selector;
173176
NSMutableArray<NSString *> *stringTypeBucket = [NSMutableArray array];
174-
_fillArgsToInvocation(signature, args, invocation, 2, stringTypeBitmaskPtr, stringTypeBucket);
177+
_fillArgsToInvocation(signature, args, invocation, 2, stringTypeBitmask, stringTypeBucket);
175178

176179
void *(^resultBlock)() = ^() {
177180
void *result = NULL;
@@ -185,10 +188,10 @@
185188
if (returnType == '@') {
186189
BOOL isNSString = [(__bridge id)result isKindOfClass:NSString.class];
187190
// highest bit is a flag for decode.
188-
BOOL decodeRetVal = (*stringTypeBitmaskPtr & (1LL << 63)) != 0;
191+
BOOL decodeRetVal = (stringTypeBitmask & (1LL << 63)) != 0;
189192
// return value is a NSString and needs decode.
190193
if (isNSString && decodeRetVal) {
191-
result = _dataForNSStringReturnValue((__bridge NSString *)result, stringTypeBitmaskPtr);
194+
result = _dataForNSStringReturnValue((__bridge NSString *)result, retType);
192195
} else {
193196
[DNObjectDealloc attachHost:(__bridge id)result
194197
dartPort:dartPort];
@@ -230,15 +233,15 @@
230233
}
231234

232235
void *
233-
native_block_invoke(void *block, void **args, Dart_Port dartPort, int64_t *stringTypeBitmaskPtr) {
234-
if (!block || !stringTypeBitmaskPtr) {
236+
native_block_invoke(void *block, void **args, Dart_Port dartPort, int64_t stringTypeBitmask, const char **retType) {
237+
if (!block) {
235238
return nullptr;
236239
}
237240
const char *typeString = DNBlockTypeEncodeString((__bridge id)block);
238241
NSMethodSignature *signature = [NSMethodSignature signatureWithObjCTypes:typeString];
239242
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
240243
NSMutableArray<NSString *> *stringTypeBucket = [NSMutableArray array];
241-
_fillArgsToInvocation(signature, args, invocation, 1, stringTypeBitmaskPtr, stringTypeBucket);
244+
_fillArgsToInvocation(signature, args, invocation, 1, stringTypeBitmask, stringTypeBucket);
242245
[invocation invokeWithTarget:(__bridge id)block];
243246
void *result = NULL;
244247
const char returnType = signature.methodReturnType[0];
@@ -249,10 +252,10 @@
249252
} else {
250253
[invocation getReturnValue:&result];
251254
BOOL isNSString = [(__bridge id)result isKindOfClass:NSString.class];
252-
BOOL decodeRetVal = (*stringTypeBitmaskPtr & (1LL << 63)) != 0;
255+
BOOL decodeRetVal = (stringTypeBitmask & (1LL << 63)) != 0;
253256
// return value is a NSString and needs decode.
254257
if (isNSString && decodeRetVal) {
255-
result = _dataForNSStringReturnValue((__bridge NSString *)result, stringTypeBitmaskPtr);
258+
result = _dataForNSStringReturnValue((__bridge NSString *)result, retType);
256259
} else {
257260
[DNObjectDealloc attachHost:(__bridge id)result
258261
dartPort:dartPort];
@@ -263,7 +266,7 @@
263266
}
264267

265268
// Use pointer as key of encoding string cache (on dart side).
266-
static const char *typeList[18] = {"sint8", "sint16", "sint32", "sint64", "uint8", "uint16", "uint32", "uint64", "float32", "float64", "object", "class", "selector", "block", "char *", "void", "ptr", "bool"};
269+
static const char *typeList[19] = {"sint8", "sint16", "sint32", "sint64", "uint8", "uint16", "uint32", "uint64", "float32", "float64", "object", "class", "selector", "block", "char *", "void", "ptr", "bool", "string"};
267270

268271
const char **
269272
native_all_type_encodings() {
@@ -321,6 +324,7 @@
321324

322325
#define PTR(type) COND(type, typeList[16])
323326

327+
// When returns struct encoding, it needs to be freed.
324328
const char *
325329
native_type_encoding(const char *str) {
326330
if (!str || strlen(str) == 0) {
@@ -369,7 +373,7 @@
369373
return str;
370374
}
371375

372-
// Returns type encodings whose need be freed.
376+
// Returns type encodings whose need to be freed.
373377
const char **
374378
native_types_encoding(const char *str, int *count, int startIndex) {
375379
int argCount = DNTypeCount(str) - startIndex;
@@ -405,6 +409,7 @@
405409
return argTypes;
406410
}
407411

412+
// Returns struct encoding which will be freed.
408413
const char *
409414
native_struct_encoding(const char *encoding) {
410415
NSUInteger size, align;
@@ -432,7 +437,12 @@
432437
}
433438
[structType appendString:@"}"];
434439
free(elements);
435-
return structType.UTF8String;
440+
// Malloc struct type, it will be freed on dart side.
441+
const char *encodeSource = structType.UTF8String;
442+
size_t typeLength = strlen(encodeSource) + 1;
443+
char *typePtr = (char *)malloc(sizeof(char) * typeLength);
444+
strlcpy(typePtr, encodeSource, typeLength);
445+
return typePtr;
436446
}
437447

438448
bool
72 Bytes
Binary file not shown.

dart_native/lib/src/ios/common/callback_register.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ _callback(
5555
// types: ret, self, _cmd, args...
5656
Pointer<Utf8> argTypePtr = typesPtrPtr.elementAt(i + 3).value;
5757
Pointer<Void> ptr = argsPtrPtrPtr.elementAt(i + argStartIndex).value.cast();
58-
if (argTypePtr.encodingForStruct == null) {
58+
if (!argTypePtr.isStruct) {
5959
ptr = ptr.cast<Pointer<Void>>().value;
6060
}
6161
dynamic arg = loadValueFromPointer(ptr, argTypePtr);

dart_native/lib/src/ios/common/pointer_encoding.dart

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,25 @@ extension TypeEncodings on Pointer<Utf8> {
3030
static final Pointer<Utf8> v = _typeEncodings.elementAt(15).value;
3131
static final Pointer<Utf8> pointer = _typeEncodings.elementAt(16).value;
3232
static final Pointer<Utf8> b = _typeEncodings.elementAt(17).value;
33+
static final Pointer<Utf8> string = _typeEncodings.elementAt(18).value;
3334

3435
// Return encoding only if type is struct.
3536
String get encodingForStruct {
36-
String result = Utf8.fromUtf8(this);
37-
if (result.startsWith('{')) {
38-
return result;
37+
if (isStruct) {
38+
return Utf8.fromUtf8(this);
3939
}
4040
return null;
4141
}
4242

43+
bool get isStruct {
44+
// ascii for '{' is 123.
45+
return cast<Uint8>().value == 123;
46+
}
47+
48+
bool get isString {
49+
return this == TypeEncodings.string;
50+
}
51+
4352
bool get isNum {
4453
bool result = this == TypeEncodings.sint8 ||
4554
this == TypeEncodings.sint16 ||
@@ -169,7 +178,7 @@ dynamic storeValueToPointer(
169178
} else if (object is Pointer && encoding.maybeCString) {
170179
Pointer<Void> tempPtr = object.cast<Void>();
171180
ptr.value = tempPtr;
172-
} else if (encoding.encodingForStruct != null) {
181+
} else if (encoding.isStruct) {
173182
// ptr is struct pointer
174183
return storeStructToPointer(ptr, object);
175184
} else {
@@ -262,6 +271,9 @@ Map<Pointer<Utf8>, Function> _loadValueStrategyMap = {
262271
Pointer<Utf8> temp = ptr.cast();
263272
return Utf8.fromUtf8(temp);
264273
},
274+
// TypeEncodings.pointer: (Pointer<Void> ptr) {
275+
// return ptr;
276+
// },
265277
TypeEncodings.v: (Pointer<Void> ptr) {
266278
return;
267279
},
@@ -290,13 +302,12 @@ dynamic loadValueFromPointer(Pointer<Void> ptr, Pointer<Utf8> encoding) {
290302
if (ptr == nullptr) {
291303
return null;
292304
}
293-
// built-in struct.
294-
String structEncoding = encoding.encodingForStruct;
295-
if (structEncoding == null) {
296-
result = ptr;
305+
// built-in struct, [ptr] is struct pointer.
306+
var struct = loadStructFromPointer(ptr, encoding.encodingForStruct);
307+
if (struct != null) {
308+
result = struct;
297309
} else {
298-
// ptr is struct pointer
299-
result = loadStructFromPointer(ptr, structEncoding);
310+
result = ptr;
300311
}
301312
}
302313
}
@@ -333,9 +344,12 @@ String loadStringFromPointer(Pointer<Void> ptr) {
333344
}
334345

335346
NativeStruct loadStructFromPointer(Pointer<Void> ptr, String encoding) {
336-
NativeStruct result;
347+
if (encoding == null) {
348+
return null;
349+
}
337350
String structName = structNameForEncoding(encoding);
338351
if (structName != null) {
352+
NativeStruct result;
339353
// struct
340354
switch (structName) {
341355
case 'CGSize':
@@ -367,8 +381,11 @@ NativeStruct loadStructFromPointer(Pointer<Void> ptr, String encoding) {
367381
break;
368382
default:
369383
}
384+
if (result != null) {
385+
return result..wrapper;
386+
}
370387
}
371-
return result..wrapper;
388+
return null;
372389
}
373390

374391
Map<String, String> _nativeTypeNameMap = {

0 commit comments

Comments
 (0)