|
32 | 32 | }
|
33 | 33 |
|
34 | 34 | void
|
35 |
| -native_signature_encoding_list(NSMethodSignature *signature, const char **typeEncodings) { |
| 35 | +native_signature_encoding_list(NSMethodSignature *signature, const char **typeEncodings, BOOL decodeRetVal) { |
36 | 36 | if (!signature || !typeEncodings) {
|
37 | 37 | return;
|
38 | 38 | }
|
39 | 39 |
|
40 | 40 | 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); |
42 | 46 | }
|
43 |
| - *typeEncodings = signature.methodReturnType; |
44 | 47 | }
|
45 | 48 |
|
46 | 49 | BOOL
|
|
104 | 107 | }
|
105 | 108 |
|
106 | 109 | 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) { |
108 | 111 | for (NSUInteger i = offset; i < signature.numberOfArguments; i++) {
|
109 | 112 | const char *argType = [signature getArgumentTypeAtIndex:i];
|
110 | 113 | NSUInteger argsIndex = i - offset;
|
|
119 | 122 | // Already put struct in pointer on Dart side.
|
120 | 123 | [invocation setArgument:args[argsIndex] atIndex:i];
|
121 | 124 | } else if (argType[0] == '@' &&
|
122 |
| - (*stringTypeBitmaskPtr >> (argsIndex + 1) & 0x1) == 1) { |
| 125 | + (stringTypeBitmask >> argsIndex & 0x1) == 1) { |
123 | 126 | const unichar *data = ((const unichar **)args)[argsIndex];
|
124 | 127 | // First four uint16_t is for data length.
|
125 | 128 | const NSUInteger lengthDataSize = 4;
|
|
141 | 144 |
|
142 | 145 | /// Return data for NSString: [--dataLength(64bit--)][--dataContent(utf16 without BOM)--]
|
143 | 146 | /// @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) { |
146 | 149 | // first bit is for return value.
|
147 |
| - *stringTypeBitmaskPtr |= 0x1; |
| 150 | + *retType = native_all_type_encodings()[18]; |
148 | 151 | NSUInteger length = 0;
|
149 | 152 | const uint16_t *utf16BufferPtr = native_convert_nsstring_to_utf16(retVal, &length);
|
150 | 153 | size_t size = sizeof(uint16_t) * length;
|
|
163 | 166 | }
|
164 | 167 |
|
165 | 168 | 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) { |
168 | 171 | return NULL;
|
169 | 172 | }
|
170 | 173 | NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
|
171 | 174 | invocation.target = object;
|
172 | 175 | invocation.selector = selector;
|
173 | 176 | NSMutableArray<NSString *> *stringTypeBucket = [NSMutableArray array];
|
174 |
| - _fillArgsToInvocation(signature, args, invocation, 2, stringTypeBitmaskPtr, stringTypeBucket); |
| 177 | + _fillArgsToInvocation(signature, args, invocation, 2, stringTypeBitmask, stringTypeBucket); |
175 | 178 |
|
176 | 179 | void *(^resultBlock)() = ^() {
|
177 | 180 | void *result = NULL;
|
|
185 | 188 | if (returnType == '@') {
|
186 | 189 | BOOL isNSString = [(__bridge id)result isKindOfClass:NSString.class];
|
187 | 190 | // highest bit is a flag for decode.
|
188 |
| - BOOL decodeRetVal = (*stringTypeBitmaskPtr & (1LL << 63)) != 0; |
| 191 | + BOOL decodeRetVal = (stringTypeBitmask & (1LL << 63)) != 0; |
189 | 192 | // return value is a NSString and needs decode.
|
190 | 193 | if (isNSString && decodeRetVal) {
|
191 |
| - result = _dataForNSStringReturnValue((__bridge NSString *)result, stringTypeBitmaskPtr); |
| 194 | + result = _dataForNSStringReturnValue((__bridge NSString *)result, retType); |
192 | 195 | } else {
|
193 | 196 | [DNObjectDealloc attachHost:(__bridge id)result
|
194 | 197 | dartPort:dartPort];
|
|
230 | 233 | }
|
231 | 234 |
|
232 | 235 | 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) { |
235 | 238 | return nullptr;
|
236 | 239 | }
|
237 | 240 | const char *typeString = DNBlockTypeEncodeString((__bridge id)block);
|
238 | 241 | NSMethodSignature *signature = [NSMethodSignature signatureWithObjCTypes:typeString];
|
239 | 242 | NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
|
240 | 243 | NSMutableArray<NSString *> *stringTypeBucket = [NSMutableArray array];
|
241 |
| - _fillArgsToInvocation(signature, args, invocation, 1, stringTypeBitmaskPtr, stringTypeBucket); |
| 244 | + _fillArgsToInvocation(signature, args, invocation, 1, stringTypeBitmask, stringTypeBucket); |
242 | 245 | [invocation invokeWithTarget:(__bridge id)block];
|
243 | 246 | void *result = NULL;
|
244 | 247 | const char returnType = signature.methodReturnType[0];
|
|
249 | 252 | } else {
|
250 | 253 | [invocation getReturnValue:&result];
|
251 | 254 | BOOL isNSString = [(__bridge id)result isKindOfClass:NSString.class];
|
252 |
| - BOOL decodeRetVal = (*stringTypeBitmaskPtr & (1LL << 63)) != 0; |
| 255 | + BOOL decodeRetVal = (stringTypeBitmask & (1LL << 63)) != 0; |
253 | 256 | // return value is a NSString and needs decode.
|
254 | 257 | if (isNSString && decodeRetVal) {
|
255 |
| - result = _dataForNSStringReturnValue((__bridge NSString *)result, stringTypeBitmaskPtr); |
| 258 | + result = _dataForNSStringReturnValue((__bridge NSString *)result, retType); |
256 | 259 | } else {
|
257 | 260 | [DNObjectDealloc attachHost:(__bridge id)result
|
258 | 261 | dartPort:dartPort];
|
|
263 | 266 | }
|
264 | 267 |
|
265 | 268 | // 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"}; |
267 | 270 |
|
268 | 271 | const char **
|
269 | 272 | native_all_type_encodings() {
|
|
321 | 324 |
|
322 | 325 | #define PTR(type) COND(type, typeList[16])
|
323 | 326 |
|
| 327 | +// When returns struct encoding, it needs to be freed. |
324 | 328 | const char *
|
325 | 329 | native_type_encoding(const char *str) {
|
326 | 330 | if (!str || strlen(str) == 0) {
|
|
369 | 373 | return str;
|
370 | 374 | }
|
371 | 375 |
|
372 |
| -// Returns type encodings whose need be freed. |
| 376 | +// Returns type encodings whose need to be freed. |
373 | 377 | const char **
|
374 | 378 | native_types_encoding(const char *str, int *count, int startIndex) {
|
375 | 379 | int argCount = DNTypeCount(str) - startIndex;
|
|
405 | 409 | return argTypes;
|
406 | 410 | }
|
407 | 411 |
|
| 412 | +// Returns struct encoding which will be freed. |
408 | 413 | const char *
|
409 | 414 | native_struct_encoding(const char *encoding) {
|
410 | 415 | NSUInteger size, align;
|
|
432 | 437 | }
|
433 | 438 | [structType appendString:@"}"];
|
434 | 439 | 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; |
436 | 446 | }
|
437 | 447 |
|
438 | 448 | bool
|
|
0 commit comments