Skip to content

Commit b673c3d

Browse files
committed
[[ Foreign Callbacks ]] Bridging and lifetime management.
There is a new LCB type 'foreign handler type'. Handler types marked as foreign will automatically bridge to C function pointers when used as a parameter type for a foreign handler. Additionally, the lifetime of C function pointers generated in this way is guaranteed to be the length of the existance of the instance they are attached to. i.e. When a handler identifier is evaluated, a handler-ref is cached against the module instance; thus if the handler-ref is subsequently bridged to a C function ptr, that handler-ref owns the C function ptr. When a module instance is finally destroyed, all handler-refs and thus any C function pointers they own are then destroyed.
1 parent 4551870 commit b673c3d

File tree

16 files changed

+334
-110
lines changed

16 files changed

+334
-110
lines changed

libfoundation/include/foundation.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1673,6 +1673,18 @@ struct MCHandlerTypeFieldInfo
16731673
// an MCHandlerTypeFieldInfo where name is null.
16741674
MC_DLLEXPORT bool MCHandlerTypeInfoCreate(const MCHandlerTypeFieldInfo *fields, index_t field_count, MCTypeInfoRef return_type, MCTypeInfoRef& r_typeinfo);
16751675

1676+
// Create a description of a foreign handler with the given signature.
1677+
// If field_count is negative, the fields array must be terminated by
1678+
// an MCHandlerTypeFieldInfo where name is null.
1679+
//
1680+
// Note: Foreign handlers and handlers are interchangeable for the most part. The
1681+
// distinction is made so that the FFI knows when it needs to bridge from an
1682+
// MCHandlerRef to a C function ptr.
1683+
MC_DLLEXPORT bool MCForeignHandlerTypeInfoCreate(const MCHandlerTypeFieldInfo *fields, index_t field_count, MCTypeInfoRef return_type, MCTypeInfoRef& r_typeinfo);
1684+
1685+
// Returns true if the handler is of foreign type.
1686+
MC_DLLEXPORT bool MCHandlerTypeInfoIsForeign(MCTypeInfoRef typeinfo);
1687+
16761688
// Get the return type of the handler. A return-type of kMCNullTypeInfo means no
16771689
// value is returned.
16781690
MC_DLLEXPORT MCTypeInfoRef MCHandlerTypeInfoGetReturnType(MCTypeInfoRef typeinfo);

libfoundation/src/foundation-private.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ struct __MCTypeInfo: public __MCValue
9393
} record;
9494
struct
9595
{
96+
bool is_foreign : 1;
9697
MCHandlerTypeFieldInfo *fields;
9798
uindex_t field_count;
9899
MCTypeInfoRef return_type;

libfoundation/src/foundation-typeinfo.cpp

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -729,8 +729,7 @@ __MCRecordTypeInfoGetBaseTypeForField (__MCTypeInfo *self,
729729

730730
////////////////////////////////////////////////////////////////////////////////
731731

732-
MC_DLLEXPORT_DEF
733-
bool MCHandlerTypeInfoCreate(const MCHandlerTypeFieldInfo *p_fields, index_t p_field_count, MCTypeInfoRef p_return_type, MCTypeInfoRef& r_typeinfo)
732+
static bool MCCommonHandlerTypeInfoCreate(bool p_is_foreign, const MCHandlerTypeFieldInfo *p_fields, index_t p_field_count, MCTypeInfoRef p_return_type, MCTypeInfoRef& r_typeinfo)
734733
{
735734
__MCTypeInfo *self;
736735
if (!__MCValueCreate(kMCValueTypeCodeTypeInfo, self))
@@ -749,7 +748,9 @@ bool MCHandlerTypeInfoCreate(const MCHandlerTypeFieldInfo *p_fields, index_t p_f
749748

750749
self -> flags |= kMCValueTypeCodeHandler;
751750

752-
for (uindex_t i = 0; i < p_field_count; ++i)
751+
self -> handler . is_foreign = p_is_foreign;
752+
753+
for (uindex_t i = 0; i < p_field_count; ++i)
753754
{
754755
self -> handler . fields[i] . type = MCValueRetain(p_fields[i] . type);
755756
self -> handler . fields[i] . mode = p_fields[i] . mode;
@@ -769,6 +770,27 @@ bool MCHandlerTypeInfoCreate(const MCHandlerTypeFieldInfo *p_fields, index_t p_f
769770
return false;
770771
}
771772

773+
MC_DLLEXPORT_DEF
774+
bool MCHandlerTypeInfoCreate(const MCHandlerTypeFieldInfo *p_fields, index_t p_field_count, MCTypeInfoRef p_return_type, MCTypeInfoRef& r_typeinfo)
775+
{
776+
return MCCommonHandlerTypeInfoCreate(false, p_fields, p_field_count, p_return_type, r_typeinfo);
777+
}
778+
779+
MC_DLLEXPORT_DEF
780+
bool MCForeignHandlerTypeInfoCreate(const MCHandlerTypeFieldInfo *p_fields, index_t p_field_count, MCTypeInfoRef p_return_type, MCTypeInfoRef& r_typeinfo)
781+
{
782+
return MCCommonHandlerTypeInfoCreate(true, p_fields, p_field_count, p_return_type, r_typeinfo);
783+
}
784+
785+
MC_DLLEXPORT_DEF
786+
bool MCHandlerTypeInfoIsForeign(MCTypeInfoRef unresolved_self)
787+
{
788+
MCTypeInfoRef self;
789+
self = __MCTypeInfoResolve(unresolved_self);
790+
791+
return self -> handler . is_foreign;
792+
}
793+
772794
MC_DLLEXPORT_DEF
773795
MCTypeInfoRef MCHandlerTypeInfoGetReturnType(MCTypeInfoRef unresolved_self)
774796
{
@@ -1217,6 +1239,8 @@ bool __MCTypeInfoIsEqualTo(__MCTypeInfo *self, __MCTypeInfo *other_self)
12171239
}
12181240
else if (t_code == kMCValueTypeCodeHandler)
12191241
{
1242+
if (self -> handler . is_foreign != other_self -> handler . is_foreign)
1243+
return false;
12201244
if (self -> handler . field_count != other_self -> handler . field_count)
12211245
return false;
12221246
if (self -> handler . return_type != other_self -> handler . return_type)

libscript/include/libscript/script.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,7 @@ void MCScriptAddDefinedTypeToModule(MCScriptModuleBuilderRef builder, uindex_t i
309309
void MCScriptAddForeignTypeToModule(MCScriptModuleBuilderRef builder, MCStringRef p_binding, uindex_t& r_type);
310310
void MCScriptAddOptionalTypeToModule(MCScriptModuleBuilderRef builder, uindex_t type, uindex_t& r_new_type);
311311
void MCScriptBeginHandlerTypeInModule(MCScriptModuleBuilderRef builder, uindex_t return_type);
312+
void MCScriptBeginForeignHandlerTypeInModule(MCScriptModuleBuilderRef builder, uindex_t return_type);
312313
void MCScriptContinueHandlerTypeInModule(MCScriptModuleBuilderRef builder, MCScriptHandlerTypeParameterMode mode, MCNameRef name, uindex_t type);
313314
void MCScriptEndHandlerTypeInModule(MCScriptModuleBuilderRef builder, uindex_t& r_new_type);
314315
void MCScriptBeginRecordTypeInModule(MCScriptModuleBuilderRef builder, uindex_t base_type);

libscript/src/script-builder.cpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -569,7 +569,7 @@ void MCScriptAddOptionalTypeToModule(MCScriptModuleBuilderRef self, uindex_t p_t
569569
__add_script_type(self, t_type, r_type);
570570
}
571571

572-
void MCScriptBeginHandlerTypeInModule(MCScriptModuleBuilderRef self, uindex_t p_return_type)
572+
static void MCScriptBeginCommonHandlerTypeInModule(MCScriptModuleBuilderRef self, bool p_is_foreign, uindex_t p_return_type)
573573
{
574574
if (self == nil ||
575575
!self -> valid)
@@ -582,12 +582,22 @@ void MCScriptBeginHandlerTypeInModule(MCScriptModuleBuilderRef self, uindex_t p_
582582
return;
583583
}
584584

585-
t_type -> kind = kMCScriptTypeKindHandler;
585+
t_type -> kind = p_is_foreign ? kMCScriptTypeKindForeignHandler : kMCScriptTypeKindHandler;
586586
t_type -> return_type = p_return_type;
587587

588588
self -> current_type = t_type;
589589
}
590590

591+
void MCScriptBeginHandlerTypeInModule(MCScriptModuleBuilderRef self, uindex_t p_return_type)
592+
{
593+
MCScriptBeginCommonHandlerTypeInModule(self, false, p_return_type);
594+
}
595+
596+
void MCScriptBeginForeignHandlerTypeInModule(MCScriptModuleBuilderRef self, uindex_t p_return_type)
597+
{
598+
MCScriptBeginCommonHandlerTypeInModule(self, true, p_return_type);
599+
}
600+
591601
void MCScriptContinueHandlerTypeInModule(MCScriptModuleBuilderRef self, MCScriptHandlerTypeParameterMode p_mode, MCNameRef p_name, uindex_t p_type)
592602
{
593603
if (self == nil ||
@@ -620,7 +630,7 @@ void MCScriptEndHandlerTypeInModule(MCScriptModuleBuilderRef self, uindex_t& r_n
620630

621631
for(uindex_t i = 0; i < self -> module . type_count; i++)
622632
{
623-
if (self -> module . types[i] -> kind != kMCScriptTypeKindHandler)
633+
if (self -> module . types[i] -> kind != t_type -> kind)
624634
continue;
625635

626636
MCScriptHandlerType *t_other_type;

0 commit comments

Comments
 (0)