djinni icon indicating copy to clipboard operation
djinni copied to clipboard

C++ export keyword

Open mrdomino opened this issue 9 years ago • 8 comments

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

mrdomino avatar Jul 09 '15 14:07 mrdomino

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.

mknejp avatar Jul 13 '15 14:07 mknejp

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>?

mrdomino avatar Jul 13 '15 15:07 mrdomino

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.

mknejp avatar Jul 13 '15 15:07 mknejp

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?

mrdomino avatar Jul 13 '15 17:07 mrdomino

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.

j4cbo avatar Jul 13 '15 18:07 j4cbo

Any news on this one? Would be great if we would have a way to add attribute((visibility("default"))) in front of static variable.

mobiletoly avatar Aug 15 '16 20:08 mobiletoly

Like most enhancements, this will happen when someone takes the time to do it. Pull requests welcome. :)

artwyman avatar Aug 15 '16 21:08 artwyman

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

niparx avatar Nov 28 '18 18:11 niparx