Skip to content

Commit 55dbfb4

Browse files
committed
Improve pointer, array in C loader.
1 parent 0a313d2 commit 55dbfb4

File tree

3 files changed

+141
-10
lines changed

3 files changed

+141
-10
lines changed

source/loaders/c_loader/source/c_loader_impl.cpp

Lines changed: 71 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -759,7 +759,8 @@ function_return function_c_interface_invoke(function func, function_impl impl, f
759759
type_id id = type_index(t);
760760
type_id value_id = value_type_id((value)args[args_count]);
761761

762-
if (id != value_id)
762+
/* We can accept pointers if we pass to an array, it is unsafe but it improves efficiency */
763+
if (id != value_id && !(value_id == TYPE_PTR && id == TYPE_ARRAY))
763764
{
764765
return metacall_error_throw("C Loader Error", 0, "",
765766
"Type mismatch in when calling %s in argument number %" PRIuS
@@ -772,15 +773,15 @@ function_return function_c_interface_invoke(function func, function_impl impl, f
772773
type_id_name(value_id));
773774
}
774775

775-
if (id == TYPE_FUNCTION)
776+
if (value_id == TYPE_FUNCTION)
776777
{
777778
c_loader_closure_value *closure = new c_loader_closure_value(static_cast<c_loader_closure_type *>(type_derived(t)));
778779

779780
c_function->values[args_count] = closure->bind(value_to_function((value)args[args_count]));
780781

781782
closures.push_back(closure);
782783
}
783-
else if (id == TYPE_STRING || id == TYPE_BUFFER)
784+
else if (value_id == TYPE_STRING || value_id == TYPE_BUFFER)
784785
{
785786
/* String, buffer requires to be pointer to a string */
786787

@@ -789,11 +790,11 @@ function_return function_c_interface_invoke(function func, function_impl impl, f
789790

790791
c_function->values[args_count] = (void *)&args[args_count];
791792
}
792-
else if (id == TYPE_PTR)
793+
else if (value_id == TYPE_PTR)
793794
{
794795
c_function->values[args_count] = args[args_count];
795796
}
796-
else if (id == TYPE_ARRAY)
797+
else if (value_id == TYPE_ARRAY)
797798
{
798799
c_loader_array_type *array = static_cast<c_loader_array_type *>(type_derived(t));
799800
void *error = NULL;
@@ -806,7 +807,7 @@ function_return function_c_interface_invoke(function func, function_impl impl, f
806807

807808
c_function->values[args_count] = array_ptr;
808809
}
809-
else if (type_id_integer(id) == 0 || type_id_decimal(id) == 0)
810+
else if (type_id_integer(value_id) == 0 || type_id_decimal(value_id) == 0)
810811
{
811812
/* Primitive types already have the pointer indirection */
812813
c_function->values[args_count] = value_data((value)args[args_count]);
@@ -883,10 +884,9 @@ function_return function_c_interface_invoke(function func, function_impl impl, f
883884

884885
for (size_t args_count = 0; args_count < args_size; ++args_count)
885886
{
886-
type t = signature_get_type(s, args_count);
887-
type_id id = type_index(t);
887+
type_id value_id = value_type_id((value)args[args_count]);
888888

889-
if (id == TYPE_ARRAY)
889+
if (value_id == TYPE_ARRAY)
890890
{
891891
c_loader_array_type::free_c_array(static_cast<void **>(c_function->values[args_count]));
892892
}
@@ -1353,6 +1353,68 @@ static int c_loader_impl_discover_ast(loader_impl impl, loader_impl_c_handle_bas
13531353
command_line_args.push_back(includes.back().c_str());
13541354
}
13551355

1356+
/* TODO: Load from memory (discover from memory) */
1357+
/*
1358+
#include <clang-c/Index.h>
1359+
#include <stdio.h>
1360+
#include <stdlib.h>
1361+
1362+
int main() {
1363+
const char *source_code =
1364+
"int add(int a, int b) {\n"
1365+
" return a + b;\n"
1366+
"}";
1367+
1368+
// Simulate an in-memory file
1369+
CXUnsavedFile unsaved_file;
1370+
unsaved_file.Filename = "example.c";
1371+
unsaved_file.Contents = source_code;
1372+
unsaved_file.Length = (unsigned long)strlen(source_code);
1373+
1374+
// Create index
1375+
CXIndex index = clang_createIndex(0, 0);
1376+
1377+
// Parse translation unit from buffer (unsaved file)
1378+
CXTranslationUnit tu;
1379+
CXErrorCode err = clang_parseTranslationUnit2(
1380+
index,
1381+
"example.c", // filename for context (matches unsaved file)
1382+
NULL, 0, // command line args
1383+
&unsaved_file, 1, // unsaved files
1384+
CXTranslationUnit_None, // options
1385+
&tu
1386+
);
1387+
1388+
if (err != CXError_Success) {
1389+
fprintf(stderr, "Failed to parse translation unit.\n");
1390+
return 1;
1391+
}
1392+
1393+
// Get the cursor to the root of the translation unit
1394+
CXCursor cursor = clang_getTranslationUnitCursor(tu);
1395+
1396+
// Visit each AST node
1397+
clang_visitChildren(
1398+
cursor,
1399+
[](CXCursor c, CXCursor parent, CXClientData client_data) {
1400+
CXString spelling = clang_getCursorSpelling(c);
1401+
CXString kind = clang_getCursorKindSpelling(clang_getCursorKind(c));
1402+
printf("Cursor: %s (%s)\n", clang_getCString(spelling), clang_getCString(kind));
1403+
clang_disposeString(spelling);
1404+
clang_disposeString(kind);
1405+
return CXChildVisit_Recurse;
1406+
},
1407+
NULL
1408+
);
1409+
1410+
// Clean up
1411+
clang_disposeTranslationUnit(tu);
1412+
clang_disposeIndex(index);
1413+
1414+
return 0;
1415+
}
1416+
*/
1417+
13561418
for (std::string file : c_handle->files)
13571419
{
13581420
/* Define the command line arguments (simulating compiler flags) */

source/reflect/source/reflect_value_type_cast.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,12 @@ value value_type_cast(value v, type_id id)
3636
return v;
3737
}
3838

39+
/* Exception raised, avoid casting */
40+
if (type_id_throwable(src_id) == 0)
41+
{
42+
return v;
43+
}
44+
3945
/* Cast from string to any type */
4046
if (type_id_string(src_id) == 0)
4147
{

source/tests/metacall_c_test/source/metacall_c_test.cpp

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,8 @@ TEST_F(metacall_c_test, DefaultConstructor)
9393

9494
/* https://github.com/metacall/core/issues/570 */
9595
{
96+
/* void apply_blur_filter(int pixels[], int width, int height) */
97+
9698
/* Call by array */
9799
{
98100
void *args[] = {
@@ -152,7 +154,68 @@ TEST_F(metacall_c_test, DefaultConstructor)
152154
metacall_value_destroy(args[2]);
153155
}
154156

155-
// TODO: double calculate_brightness(int pixels[], int size)
157+
/* double calculate_brightness(int pixels[], int size) */
158+
159+
/* Call by array */
160+
{
161+
void *args[] = {
162+
metacall_value_create_array(NULL, 100),
163+
metacall_value_create_int(100)
164+
};
165+
166+
void **array_ptr = metacall_value_to_array(args[0]);
167+
168+
for (int i = 0; i < 100; ++i)
169+
{
170+
array_ptr[i] = metacall_value_create_int(i);
171+
}
172+
173+
std::cout << "value: " << args[0] << std::endl;
174+
std::cout << "array: " << array_ptr << std::endl;
175+
176+
ret = metacallv("calculate_brightness", args);
177+
178+
EXPECT_NE((void *)NULL, (void *)ret);
179+
180+
EXPECT_EQ((enum metacall_value_id)metacall_value_id(ret), (enum metacall_value_id)METACALL_DOUBLE);
181+
182+
std::cout << "result: " << metacall_value_to_double(ret) << std::endl;
183+
184+
EXPECT_EQ((double)metacall_value_to_double(ret), (double)49.5);
185+
186+
metacall_value_destroy(ret);
187+
188+
metacall_value_destroy(args[0]);
189+
metacall_value_destroy(args[1]);
190+
}
191+
192+
/* Call by pointer */
193+
{
194+
int array[100];
195+
196+
void *args[] = {
197+
metacall_value_create_ptr(array),
198+
metacall_value_create_int(100)
199+
};
200+
201+
for (int i = 0; i < 100; ++i)
202+
{
203+
array[i] = i;
204+
}
205+
206+
ret = metacallv("calculate_brightness", args);
207+
208+
EXPECT_NE((void *)NULL, (void *)ret);
209+
210+
EXPECT_EQ((enum metacall_value_id)metacall_value_id(ret), (enum metacall_value_id)METACALL_DOUBLE);
211+
212+
std::cout << "result: " << metacall_value_to_double(ret) << std::endl;
213+
214+
metacall_value_destroy(ret);
215+
216+
metacall_value_destroy(args[0]);
217+
metacall_value_destroy(args[1]);
218+
}
156219
}
157220

158221
/* File with dependencies */

0 commit comments

Comments
 (0)