Skip to content
This repository was archived by the owner on Aug 31, 2021. It is now read-only.

Commit e3ac040

Browse files
authored
Merge pull request #6203 from livecodeali/feature-proper_list_to_carray
[[ FFI ]] Add ability to convert proper list to c-array
2 parents 0e40142 + c5d7735 commit e3ac040

File tree

3 files changed

+93
-0
lines changed

3 files changed

+93
-0
lines changed

libfoundation/include/foundation.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3391,6 +3391,12 @@ MC_DLLEXPORT bool MCProperListCreate(const MCValueRef *values, uindex_t length,
33913391
// foreign value is created (MCForeignValueRef).
33923392
MC_DLLEXPORT bool MCProperListCreateWithForeignValues(MCTypeInfoRef type, const void *values, uindex_t value_count, MCProperListRef& r_list);
33933393

3394+
// Create a c-array of foreign values from the given list. The original list is
3395+
// not released. Ownership of the foreign value array is passed to the caller.
3396+
// p_typeinfo must be a foreign typeinfo. If any value in the list is not of the
3397+
// given type, or cannot be exported as that type, this returns false.
3398+
MC_DLLEXPORT bool MCProperListConvertToForeignValues(MCProperListRef list, MCTypeInfoRef p_typeinfo, void*& r_values_ptr, uindex_t& r_values_count);
3399+
33943400
// Create an empty mutable list.
33953401
MC_DLLEXPORT bool MCProperListCreateMutable(MCProperListRef& r_list);
33963402

libfoundation/src/foundation-proper-list.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,50 @@ bool MCProperListCreateWithForeignValues(MCTypeInfoRef p_typeinfo, const void *p
127127
return true;
128128
}
129129

130+
MC_DLLEXPORT_DEF
131+
bool MCProperListConvertToForeignValues(MCProperListRef self, MCTypeInfoRef p_typeinfo, void*& r_values_ptr, uindex_t& r_values_count)
132+
{
133+
__MCAssertIsForeignTypeInfo(p_typeinfo);
134+
135+
const MCForeignTypeDescriptor *t_descriptor =
136+
MCForeignTypeInfoGetDescriptor(p_typeinfo);
137+
138+
uindex_t t_values_count = MCProperListGetLength(self);
139+
void *t_values = nullptr;
140+
if (!MCMemoryNew(t_values_count * t_descriptor->size, t_values))
141+
{
142+
return false;
143+
}
144+
145+
byte_t *t_values_ptr = (byte_t*)t_values;
146+
for(uindex_t t_index = 0; t_index < t_values_count; t_index++)
147+
{
148+
MCValueRef t_value = MCProperListFetchElementAtIndex(self, t_index);
149+
if (MCValueGetTypeInfo(t_value) == p_typeinfo)
150+
{
151+
MCMemoryCopy(t_values_ptr, MCForeignValueGetContentsPtr(t_value), t_descriptor->size);
152+
}
153+
else if (MCValueGetTypeInfo(t_value) == t_descriptor->bridgetype)
154+
{
155+
if (!t_descriptor->doexport(t_descriptor, t_value, false, t_values_ptr))
156+
{
157+
MCMemoryDelete(t_values);
158+
return false;
159+
}
160+
}
161+
else
162+
{
163+
MCMemoryDelete(t_values);
164+
return false;
165+
}
166+
t_values_ptr += t_descriptor->size;
167+
}
168+
169+
r_values_ptr = t_values;
170+
r_values_count = t_values_count;
171+
172+
return true;
173+
}
130174

131175
MC_DLLEXPORT_DEF
132176
bool MCProperListCreateMutable(MCProperListRef& r_list)

tests/lcb/vm/foreign-invoke.lcb

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,4 +91,47 @@ end handler
9191

9292
--------
9393

94+
foreign handler MCProperListConvertToForeignValues(in pList as List, in pTypeInfo as Pointer, \
95+
out rCArray as Pointer, out rCount as LCUIndex) returns CBool binds to "<builtin>"
96+
foreign handler MCAggregateTypeInfo(in pBinding as String, out rTypeInfo as Pointer) returns CBool binds to "<builtin>"
97+
foreign handler MCValueRelease(in pValue as Pointer) returns nothing binds to "<builtin>"
98+
foreign handler MCMemoryDelete(in pBlock as Pointer) returns nothing binds to "<builtin>"
99+
100+
unsafe handler CreateCArray(in pList as List, in pAggregateBinding as String, out rPointer as Pointer, out rCount as Integer) returns Boolean
101+
variable tCArray as Pointer
102+
variable tCount as Integer
103+
variable tTypeInfo as Pointer
104+
if not MCAggregateTypeInfo(pAggregateBinding, tTypeInfo) then
105+
return false
106+
end if
107+
108+
variable tSuccess as Boolean
109+
put MCProperListConvertToForeignValues(pList, tTypeInfo, tCArray, tCount) into tSuccess
110+
111+
MCValueRelease(tTypeInfo)
112+
if not tSuccess then
113+
return false
114+
end if
115+
116+
put tCArray into rPointer
117+
put tCount into rCount
118+
return true
119+
end handler
120+
121+
-- Create a c-array of structs and delete it
122+
public handler TestProperListToCArray()
123+
variable tList as List
124+
put [[true, true, true], [false, false, false]] into tList
125+
variable tArray as Pointer
126+
variable tCount as Integer
127+
unsafe
128+
test "create c-array of structs" when \
129+
CreateCArray(tList, "aaa", tArray, tCount)
130+
131+
test "c-array has correct length" when tCount is 2
132+
133+
-- Hopefully this would crash if there was a memory issue
134+
MCMemoryDelete(tArray)
135+
end unsafe
136+
end handler
94137
end module

0 commit comments

Comments
 (0)