Controlling the ref type in a Vapi file - vala

I'm trying to write a Vapi file for MessagePack and am having a couple of issues, the first being that the resulting msgpack_object_print is incorrect because of the reference type of one of the parameters. The header file expects
void msgpack_object_print(FILE* out, msgpack_object o);
and my Vapi file contains
[CCode (instance_pos = 1.1)]
public void print (Posix.FILE out);
which generates the C output
msgpack_object_print (_tmp13_, &obj);
where obj is type msgpack_object *. This creates the error
examples/simple.c:173:34: error: incompatible type for argument 2 of ‘msgpack_object_print’
and it disappears if I remove the & from the generated C. So I'm wondering what my Vapi should contain to result in the correct output?

You can designated your msgpack_object class as [SimpleType] and it will be copied by value rather than by reference.

I have written a partial VAPI for MessagePack if you want to contribute back by using and testing it.
https://github.com/valum-framework/vala-extra-vapis/blob/msgpack/msgpack.vapi
Like already said, you need to use the [SimpleType] annotation on the class to have your type passed by value.
EDIT: Just adding that for bindings, it's a good thing to keep them in nemequ/vala-extra-vapis repository.

Related

The argument type 'ListOf5' can't be assigned to the parameter type 'ListOf5'

I need to implement an abstract class function, which own a an specific data type. But I need inside my logic layer to make the attribute which is going to be passed as a dynamic data type. But when i Pass it to the function, i am sure that its data type will be as needed. So, i type (product.value.pickedImages) as ListOf5) . But it does an Exception.
The Abstract Class Code Is:
Future<Either<FireStoreServerFailures, List<String>>> uploadProductImages(
{required ListOf5<File> images});
The Implementation Code Is:
Future<Option<List<String>>> _uploadImagesToFirestorage() async {
return await productRepo
.uploadProductImages(
images: (product.value.pickedImages) as ListOf5<File>) // Exception
}
The Exception Is:
The argument type 'ListOf5 < dynamic>' can't be assigned to the
parameter type 'ListOf5 < File>'.
You are trying to cast the List from List<dynamic> to List<String>.
Instead, you should cast each item, using something like this:
void main() {
List<dynamic> a = ['qwerty'];
print(List<String>.from(a));
}
Not sure about the implementation of this ListOf5 though...
The cast (product.value.pickedImages) as ListOf5<File> fails.
It fails because product.value.pickedImages is-not-a ListOf5<File>, but instead of ListOf5<dynamic> (which may or may not currently contain only File objects, but that's not what's being checked).
Unlike a language like Java, Dart retains the type arguments at run-time(it doesn't do "erasure"), so a ListOf5<dynamic> which contains only File objects is really different from a ListOf5<File> at run-time.
You need to convert the ListOf5<dynamic> to a ListOf5<File>.
How to do that depends on the type ListOf5, which I don't know.
For a normal List, the two most common options are:
(product.value.pickedImages).cast<File>(). Wraps the existing list and checks on each read that you really do read a File. It throws if you ever read a non-File from the original list. Perfectly fine if you'll only read the list once.
List<File>.of(product.value.pickedImages). Creates a new List<File> containing the values of product.value.pickedImages, and throws if any of the values are not File objects. Requires more memory (because it copies the list), but fails early in case there is a problem, and for small lists, the overhead is unlikely to be significant. If you read the resulting list many times, it'll probably be more efficient overall.
If the ListOf5 class provides similar options, you can use those. If not, you might have to build a new ListOf5 manually, casting each element of the existing ListOf5<dynamic> yourself.
(If the ListOf5 class is your own, you can choose to add such functionality to the class).

Objective-C class as C pointer type

clang builtin function "__builtin_NSStringMakeConstantString" returns const NSConstantString*,
that is not an Objective-C retainable object.
I want to replace this function with my own, but there seems to be no way to declare NSConstantString* as non-Objective-C pointer in Objective-C++ (you can do it in Objective-C by using struct NSConstnatString*). I am sure, that this function returns NSConstantString, because the following two lines output PK16NSConstantString:
printf("%s\n", typeid(__builtin___NSStringMakeConstantString("foo")).name());
printf("%s\n", typeid(const NSConstantString*).name());
Whenever I try to execute the following code I get error "Cannot initialize a variable of type 'const NSConstantString *' with an rvalue of type 'const NSConstantString *'":
const NSConstantString* a = __builtin___NSStringMakeConstantString("foo");
Everything works OK if I add bridge cast, so this means that NSConstantString* is returned as "raw" Objective-C pointer, but I have to create a function that returns exactly the same result as "__builtin_NSStringMakeConstantString", so I have no option to use __bridge.
Whenever I try to return const NSConstantString* from a function, it is always returned as an Objective-C retainable pointer and there seems to be no way to declare it as C pointer except this:
typedef typeof __builtin___NSStringMakeConstantString("") rawNSConstnatStringPtr;
So the question is: Is there a way to declare a nonretainable pointer to NSConstantString* (without using typeof)?
You think _builtin__NSStringMakeConstant returns NSConstantString, because the compiler is tricking you.
I suggest you check out the clang source code: http://llvm.org/docs/GettingStarted.html#git-mirror
Then search the source code: git grep __builtin___NSStringMakeConstantString. You find that it's defined in include/clang/Basic/Builtins.def like this:
BUILTIN(__builtin___NSStringMakeConstantString, "FC*cC*", "nc")
The second argument is the function signature, and the comment at the top of the file explains what it means. The FC* part is the return type, and means “constant CFString const pointer”. That makes sense since CFString and NSString are toll-free bridged.
But it doesn't make sense because the error message specifically mentions NSConstantString. So git grep -w NSConstantString to see where that's coming from. You eventually find method ASTContext::getCFConstantStringType in lib/ast/ASTContext.cpp. This method creates a struct type declaration with the identifier NSConstantString, but it never adds the declaration to any scope (it doesn't call PushOnScopeChains or AddDecl). So the NSConstantString identifier can appear in diagnostics, but you cannot access the type by name in your source code. The NSConstantString type declared in NSString.h is, as far as the compiler is concerned, unrelated to this synthesized type.
Anyway, the important question is why you want to override __builtin___NSStringMakeConstantString, which you did not say. If it's because you want to use your own constant string class, you're going about it the wrong way.
I don't think you can override that function, because it is built in to the compiler. You would need to modify the compiler source code if you want to change its meaning.
Also, I don't think the compiler actually uses that function to create Objective-C string literals. Running git grep __builtin___NSStringMakeConstantString doesn't turn up any places where the compiler generates a call to it. The compiler handles #"string" syntax in lib/Parse/ParseObjc.cpp and lib/Sema/SemaExprObjC.cpp (look for methods named ParseObjCStringLiteral in both files). The compiler looks up the NSConstantString type by name (which means it should get the one from the NSString.h header file) and creates an instance of ObjCStringLiteral with that type.
You should be able to make it look up a different class for the constant string type (instead of NSConstantString) using the -fconstant-string-class command-line flag, but I don't know how well that works. This question implies that it might not work. Even if it does work, I think you're constrained to using the same memory layout as NSConstantString, in which case, why bother using a different class?

How does Orika decide when to use converter

I am trying to understand when does Orika use converters to do the mapping versus direct casting.
I have the following mapping:
Class A {
Map<String, Object> props;
}
Class B {
String bStr;
int bInt;
}
My mapping is defined as props['aStr'] => bStr and props['aInt'] => bInt
When I look at the generated code, I see that for the String case, it uses a converter and calls its convert method for the transformation:
destination.setBStr("" + ((ma.glasnost.orika.Converter)usedConverters[0]).convert(
((java.lang.Object) ((java.util.Map) source.getProps().get("aStr"),
(ma.glasnost.orika.metadata.Type) usedTypes[0]))
But, for the integer case it directly casts it like this:
destination.setBInt((java.lang.Integer)(java.lang.Object) ((java.util.Map)
source.getProps().get("aInt")))
The above line of code ends up giving class cast exception.
For fixing this issue, I was thinking along the lines of using a custom converter but if the above line of code doesn't use the converter then that wont work.
Of course, I can always do this is in my custom mapper but just trying to understand how the code is generated for type conversion.
Thanks!!
In Orika there is two stages: config-time and runtime, as optimization Orika resolve all used converter in the config-time and cache them into each generated mapper so it will be accessible directly O(1) but in the config time it will try to find in a list O(n) of registered converters which one "canConvert" between two given types, canConvert is a method in Converter interface .
So this solution offer the best of the two worlds:
A very flexible way to register a converter with arbitrary conditions
An efficient resolution and conversion operation in the runtime.
Orika by default, leverage the existence of .toString in every object to offer implicit coercion to String for every Object. The problem here is that there is no Converter from Object to Integer.
Maybe this can be an issue of error reporting. Ideally Orika should report that an Object have to be converted to Integer and there is no appropriate converter registered.

How to initialize Type int()?

When trying to initialize a Type to \int(), as found in http://tutor.rascal-mpl.org/Rascal/Libraries/analysis/m3/Core/modifiers/modifiers.html#/Rascal/Libraries/lang/java/m3/AST/Declaration/Declaration.html , rascal throws an error saying "Expected Type, but got TypeSymbol".
This is the code I used:
Type inttype = \int();
What is the proper way to initialize a Type variable to \int()?
To solve the problem you can write:
Type myIntType = Type::\int();
More explanation follows. The \int() constructor is defined at least twice in different places:
In the abstract syntax tree definition of Java types that are used in Declarations. It is the representation of the word int in source code.
In the TypeSymbol definition in java::lang::m3::Core. There \int() represents a symbolic type.
They have the same name because they point to the same concept, but in different representations. The first is just used for a direct representation of source code, the second is used for its abstract symbolic interpretation.
To distinguish between the two representations you should either import the module that defines the AST nodes, or import the module that defines the TypeSymbols. If you happen to have both imported, you should choose a representation explicitly:
Type myIntType = Type::\int();
TypeSymbol mySymbol = TypeSymbol::\int();
So to finally explain the error message, the system chose the second kind of \int()` in TypeSymbol to build a value, and you tried to assigned it to a variable of the first kind.
\int() is a TypeSymbol, I think you're looking for
Type inttype = int();

Is there a way for having the same string readable and editable from C and Objective-C?

I have the following problem: an iOS app written with Objective-C (as usual) which uses parts of code written with C. The C code is the core of the application, the code written with Objective-C uses the job done by C and coordinates the whole application.
For doing its job, the C code reads something from a preferences file, whose name is cabled in a C file. Is it possible (in the C code) to read the name of the file at run-time rather then at compile-time? The idea is to modify a string with Objective-C and let the C code to read that string.
Looks like you have a hard-coded file name in a C file. That's not a good design; in an iOS application, you never know what your path names are, and the notion of the current folder is muddled in a GUI app. Make the file name a parameter of the C function, and pass it from the Objective C side, along with a full path. Depending on the placement of the file, it can be in your app's bundle, or in the document folder, or somewhere else - you know better.
Yes, you can make file name a variable instead of a constant. The variable datatype would be char*.
EDIT re: comments: to work around this, try setting the current folder from the ObjC side. Before calling the C function, call [NSFileManager setCurrentDirectoryPath:], passing the folder where the file is (again, I don't know what it might be). Then the hard-coded file name would work.
Assuming your .c file looks something like this:
#include <stdbool.h>
static const char *_prefsFilename = "userprefs.css";
bool readPrefs() {
FILE *fp = fopen(_prefsFilename, "r");
....
}
Then you simply need to add a function to allow _prefsFilename to be set before an attempt is made to use it to open the file:
void setPrefsFilename(const char *prefsFilename) {
_prefsFilename = prefsFilename;
}
and ensure you call it before calling readPrefs().
This is all assumption of course, but that's all I have to work with.

Resources