@@ -516,6 +516,19 @@ class c_loader_closure_value
516516 }
517517};
518518
519+ class c_loader_pointer_type : public c_loader_type_impl
520+ {
521+ protected:
522+ loader_impl impl;
523+ CXType cx_type;
524+
525+ public:
526+ c_loader_pointer_type (loader_impl impl, CXType cx_type) :
527+ impl (impl), cx_type(cx_type) {}
528+
529+ ~c_loader_pointer_type () {}
530+ };
531+
519532std::string c_loader_impl_cxstring_to_str (const CXString &s)
520533{
521534 std::string result = clang_getCString (s);
@@ -662,6 +675,7 @@ function_return function_c_interface_invoke(function func, function_impl impl, f
662675 for (size_t args_count = 0 ; args_count < args_size; ++args_count)
663676 {
664677 type t = signature_get_type (s, args_count);
678+ type_impl impl_type = type_derived (t);
665679 type_id id = type_index (t);
666680 type_id value_id = value_type_id ((value)args[args_count]);
667681
@@ -687,13 +701,22 @@ function_return function_c_interface_invoke(function func, function_impl impl, f
687701
688702 closures.push_back (closure);
689703 }
690- else if (id == TYPE_STRING)
704+ else if (id == TYPE_STRING || (id == TYPE_PTR && impl_type != nullptr ) )
691705 {
692- /* String requires to be pointer to a string */
706+ /* String requires to be pointer to a string and
707+ Pointer requires to be pointer to pointer */
693708 c_function->values [args_count] = value_create_ptr ((value)args[args_count]);
694709 }
695710 else
696711 {
712+ /* In case of (id == TYPE_PTR && impl_type == nullptr it means that
713+ the parameter is normally int*, long*, etc... we just let the pointer
714+ be passed as it is because it cannot output a pointer, only modify the contents
715+ */
716+
717+ /* TODO: Check if types are not equal and do a casting?
718+ Note: It will involve destroying the new casted values */
719+
697720 c_function->values [args_count] = value_data ((value)args[args_count]);
698721 }
699722 }
@@ -741,9 +764,27 @@ function_return function_c_interface_invoke(function func, function_impl impl, f
741764 for (size_t args_count = 0 ; args_count < args_size; ++args_count)
742765 {
743766 type t = signature_get_type (s, args_count);
767+ type_impl impl_type = type_derived (t);
744768 type_id id = type_index (t);
745769
746- if (id == TYPE_STRING)
770+ /* This is very tricky, if the type was a pointer to pointer, if it
771+ replaced the target pointer we have to update it in the MetaCall value,
772+ for example:
773+ void f(char **str_ptr)
774+ {
775+ *str_ptr = "aaa";
776+ }
777+ In order to make it work we have to recreate the metacall value, this is
778+ highly unsafe if we mix types because we will use the type info of the
779+ underlaying type in order to recreate it, in this example, a string
780+ */
781+ if (id == TYPE_PTR && impl_type != nullptr )
782+ {
783+ // TODO: Reconstruct the pointer value from the type info
784+
785+ value_type_destroy (c_function->values [args_count]);
786+ }
787+ else if (id == TYPE_STRING)
747788 {
748789 /* Clear the pointer to string allocated before */
749790 value_type_destroy (c_function->values [args_count]);
@@ -978,6 +1019,13 @@ static type_id c_loader_impl_clang_type(loader_impl impl, CXCursor cursor, CXTyp
9781019 {
9791020 return c_loader_impl_clang_type (impl, cursor, pointee_type, impl_type);
9801021 }
1022+ /* Check for pointers to pointers, in this case we need the type info for reconstructing the data */
1023+ else if (pointee_type.kind == CXType_Pointer)
1024+ {
1025+ c_loader_pointer_type *pointer_type = new c_loader_pointer_type (impl, cx_type);
1026+
1027+ *impl_type = static_cast <c_loader_pointer_type *>(pointer_type);
1028+ }
9811029
9821030 return TYPE_PTR;
9831031 }
0 commit comments