djinni
djinni copied to clipboard
C++ export keyword
There's a common idiom of using PROJECT_EXPORT
or what-have-you to expand to __declspec(dllexport)
or dllimport on Windows, and __attribute__((visibility("default")))
on POSIX. For projects where a library is used on desktop platforms as well as in Objective-C and Android, it'd be handy to be able to emit a symbol like that on all generated C++ interfaces.
Would a --cpp-annotate-symbol <ANNOTATION-SYMBOL>
flag be reasonable for this?
See also: https://gcc.gnu.org/wiki/Visibility
For the C++ interface
base class it only really matters for static methods, everything else is found via vtable dispatch for which the functions do not need to be publicly exported by the binary.
It may also be necessary for operators on records, however the easier solution there might be to simply generate the implementations inline.
If the annotation symbol is user-defined it probably also depends on a header that needs to be included in the generated files, requiring a second option for that.
I about 85% believe you on the vtable dispatch, but do you have any external sources on it?
For static methods, we could just stick the visibility attribute on the implementation, but I think we need the __declspec(dllimport)
on the interface, so maybe this should be --cpp-annotate-static <SYMBOL>
?
The vtable pointer is nothing but a pointer to an array of function pointers. As long as the consumer of your library can get that vtable pointer it can call the function pointers stored in that array.
If your derived class is exposed in the header then the vtable for that class must be a public symbol of the binary (but this is not the case for the interface +c
base classes as they have no implementation). If instead your derived class is not available in a public header and you use a factory function (as is required in Djinni interface +c
) then you get back a fully constructed object with the correct vtable pointer pointing to a private data structure in your binary. No symbol lookup involved.
That is why COM works and everybody is doing it basically the same way with minor variations. http://blogs.msdn.com/b/oldnewthing/archive/2004/02/05/68017.aspx
For static methods, we could just stick the visibility attribute on the implementation, but I think we need the
__declspec(dllimport)
on the interface, so maybe this should be--cpp-annotate-static <SYMBOL>
?
It's really just a linker annotation. You cannot have __declspec(dllimport)
in the declaration when building the DLL, I'm pretty sure that makes your build fail, that's why it's usually a macro that expands to either __declspec(dllimport)
or __declspec(dllexport)
depending on another macro that tells you whether you are building the DLL or not. Similar with the POSIX stuff. That's why it is going depend on a user-provided header.
And it's also required on record operators, so not just static stuff.
Good to know re the vtable stuff.
I was skipping a few steps for expediency when talking about the dll import/export stuff -- I'm talking about a macro that would expand to dllimport or dllexport depending on whether you were building the DLL or not, or a visibility annotation if you were building on a platform where such a thing made sense to have.
And I'd missed that last part about requiring a user-provided header, but yes, that's correct.
How about --cpp-annotation
and --cpp-user-header
?
Seems good to me. I'd like to have some hint at the purpose of the annotation in the flag name - so either --cpp-export-annotation
or --cpp-visibility-annotation
seems fine to me.
Any news on this one? Would be great if we would have a way to add attribute((visibility("default"))) in front of static variable.
Like most enhancements, this will happen when someone takes the time to do it. Pull requests welcome. :)
So, here is a use case. I want to create an iOS framework. And that framework (dynamic) consist of Djinin created files. Thing is, what when I try to use that framework, I got link errors: "Undefined symbols for architecture ..." with a list of Djinni generated classes (@interfaces and @protocols).
Library is build with '-fvisibility=hidden' flag.
I run nm -gm
command in order to see, what is inside framework. And I don't see there any of Djinni generated resources.
Next, I add attribute((visibility("default"))) in Djinni generated file, so it looks like this:
__attribute__((visibility("default"))) @interface My_Awasome_Name : NSObject
.
Compile it, rerun nm -gm
and... I can see symbol there:
(__DATA,__objc_data) external _OBJC_CLASS_$_My_Awasome_Name
Then I compile my project, which use this framework, and there is no link errors "Undefined symbols for architecture...", related to My_Awasome_Name
I will look around into code and will try to add such feature