I’m creating a plugin for Claws Mail to allow tighter integration with Haiku. Among my goals there is a Deskbar replicant.
I’ve already succesfully built a standalone application that adds a replicant to the Deskbar and I would like to do the same when the plugin is loaded. Claws plugins are standard shared libraries that export specific functions calles upon loading. Nothing critical except they must be written in C and all C++ code must be wrapped in C functions. No big deal.
I have imported all the classes from the other project into the plugin but every time I try to add the replicant with AddItem passing an entry_ref to the plugin file itself, I get a Name not found" error -2147483641.
The Be Book reads that negative values are “message-sending error(s)”, what does that mean? What could be the cause?
I’m happy to share more details or the whole code if necessary.
Many thanks!
My guess would be something wrong with the Archive() or Instantiate() methods not reading the class name from the BMessage. Have you looked at the syslog? I frequently see failed instantiation messages there with a bit more detail.
After digging a bit, I think the Be Book is right. B_NAME_NOT_FOUND is returned by one of the BMessage methods.
When a replicant is added, the Deskbar calls Archive() on the target BView then it loads the add-on and calls instantiate_deskbar_item().
The constructor of the replicant view gets called but not Archive(), I think that the “add_on” field is not retrieved at this point.
Thing is that I don’t understand why the same exact code works as a standalone application.
Hard to say without seeing the code or getting a better error message. Could be an application signature problem if the plugin doesn’t have one set or something.
Try printing the BMessage with the PrintToStream() method and look for differences?
I had some surprises with how replicants are loaded, I think some parts of the code rely on finding the app (or add-on) by its signature using a query. Does your add-on file have a MIME signature set? (in its resources and in its attributes) Is that signature also included in the message?
I think I’ve said the contrary but Archive() does not get called, actually. I can’t print the message content, then.
The signature is set and included in the file attributes, it is also included in the message:
status_t
DeskbarReplicant::Archive(BMessage* archive, bool deep) const
{
status_t status = BView::Archive(archive, deep);
if (status == B_OK)
status = archive->AddString("add_on", kApplicationSignature);
if (status == B_OK)
status = archive->AddString("class", kClassName);
BString str;
str << "Archive():" << status;
BAlert("Haiku Plugin", str,
"OK", NULL, NULL,
B_WIDTH_AS_USUAL, B_OFFSET_SPACING, B_WARNING_ALERT).Go();
return status;
}
Considering that Archive is not called, it’s now clear why I get the “Name not found” message.
Now it comes the tricky thing.
If I move all the replicant logic to a separate add-on something moves on and Archive() and instantiate_deskbar_item() are called. I get other errors but that’s another story.
I appreciate this is an unconventional scenario, in fact the plugin is made of a C file (haiku.c, with the hooks Claws require to load and initialize the plugin) and C++ files which implement all the Haiku specific logic.
There is no way to make the main entry point a C++ file, it must be C as it includes headers from Claws with GTK/glib specific stuff. For example, there are functions that use C++ reserved keywords as a parameter (class).
My suspicion is that the shared library built in this mixed mode does not get along with the way Deskbar loads an add-on. Could it make sense?
According to the gcc docs it means optimization is turned on(using -Os, -O2, -O3, etc…) and gcc thinks those methods aren’t going to be called so it optimizes them into a separate ‘cold’ group for performance. You could try disabling optimization or marking those methods with the ‘hot’ keyword.
It’s clear that the resulting shared library compiled with a mix of C and C++ is not well digested by load_add_on(). At least the one I have compiled.
Even the Debugger does not allow me to add breakpoints when the plug-in is loaded into Claws.
I have used a standard makefile with the makefile engine adding the .c and .cpp all together.
Maybe is there a better way to do it?