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.
all errors in haiku are negative, there is a cli application you can call that sais what the code means (i think called error?)
I think it’s equivalent to calling strerror()?
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.
Nothing useful in the syslog, unfortunately.
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:
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);
str << "Archive():" << status;
BAlert("Haiku Plugin", str,
"OK", NULL, NULL,
B_WIDTH_AS_USUAL, B_OFFSET_SPACING, B_WARNING_ALERT).Go();
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?
Here’s the output of readelf from the plugin with the C code (haiku.c):
19: 0000000000000000 0 FILE LOCAL DEFAULT ABS DeskbarReplicant.cpp
21: 0000000000004d5a 21 FUNC LOCAL DEFAULT 11 _ZN16DeskbarReplicant5_InitEv.cold
23: 0000000000004d70 16 FUNC LOCAL DEFAULT 11 _ZN16DeskbarReplicantC2E5BRecti.cold
24: 0000000000004d80 16 FUNC LOCAL DEFAULT 11 _ZN16DeskbarReplicantC2EP8BMessage.cold
25: 0000000000004d90 42 FUNC LOCAL DEFAULT 11 _ZN16DeskbarReplicant11InstantiateEP8BMessage.cold
26: 0000000000004dba 16 FUNC LOCAL DEFAULT 11 _ZN16DeskbarReplicant15_ForwardMessageEPKcP8BMessage.cold
27: 0000000000004dca 21 FUNC LOCAL DEFAULT 11 _ZN16DeskbarReplicant23_QuitApplicationAndWaitEPKc.cold
29: 0000000000004de0 24 FUNC LOCAL DEFAULT 11 _ZNK16DeskbarReplicant7ArchiveEP8BMessageb.cold
31: 0000000000004e1e 16 FUNC LOCAL DEFAULT 11 _ZN16DeskbarReplicant16AttachedToWindowEv.cold
32: 0000000000004e2e 108 FUNC LOCAL DEFAULT 11 _ZN16DeskbarReplicant27_SendComposeMessageShortcutEv.cold
33: 0000000000004e9a 244 FUNC LOCAL DEFAULT 11 _ZN16DeskbarReplicant9MouseDownE6BPoint.cold
59: 0000000000005750 91 FUNC GLOBAL DEFAULT 11 _ZN16DeskbarReplicantC2E5BRecti
72: 0000000000008020 24 OBJECT WEAK DEFAULT 19 _ZTI16DeskbarReplicant
73: 0000000000005570 19 FUNC GLOBAL DEFAULT 11 _ZN16DeskbarReplicantD2Ev
87: 0000000000008038 528 OBJECT WEAK DEFAULT 19 _ZTV16DeskbarReplicant
88: 0000000000005590 35 FUNC GLOBAL DEFAULT 11 _ZN16DeskbarReplicantD0Ev
90: 0000000000005920 115 FUNC GLOBAL DEFAULT 11 _ZN16DeskbarReplicant15_ForwardMessageEPKcP8BMessage
94: 0000000000005bf0 204 FUNC GLOBAL DEFAULT 11 _ZN16DeskbarReplicant16AttachedToWindowEv
99: 0000000000005750 91 FUNC GLOBAL DEFAULT 11 _ZN16DeskbarReplicantC1E5BRecti
100: 0000000000005cc0 1159 FUNC GLOBAL DEFAULT 11 _ZN16DeskbarReplicant27_SendComposeMessageShortcutEv
108: 0000000000005600 221 FUNC GLOBAL DEFAULT 11 _ZN16DeskbarReplicant4DrawE5BRect
116: 0000000000006150 187 FUNC GLOBAL DEFAULT 11 _ZN16DeskbarReplicant15MessageReceivedEP8BMessage
136: 0000000000006b80 19 OBJECT WEAK DEFAULT 13 _ZTS16DeskbarReplicant
137: 0000000000005a20 272 FUNC GLOBAL DEFAULT 11 _ZNK16DeskbarReplicant7ArchiveEP8BMessageb
144: 00000000000057b0 50 FUNC GLOBAL DEFAULT 11 _ZN16DeskbarReplicantC1EP8BMessage
201: 00000000000058c0 95 FUNC GLOBAL DEFAULT 11 _ZN16DeskbarReplicant25_LaunchApplicationAndWaitEPKc
207: 00000000000059a0 128 FUNC GLOBAL DEFAULT 11 _ZN16DeskbarReplicant23_QuitApplicationAndWaitEPKc
212: 00000000000055c0 51 FUNC GLOBAL DEFAULT 11 _ZN16DeskbarReplicant5PulseEv
241: 0000000000005570 19 FUNC GLOBAL DEFAULT 11 _ZN16DeskbarReplicantD1Ev
242: 00000000000056e0 109 FUNC GLOBAL DEFAULT 11 _ZN16DeskbarReplicant5_InitEv
245: 0000000000006210 1104 FUNC GLOBAL DEFAULT 11 _ZN16DeskbarReplicant9MouseDownE6BPoint
252: 00000000000057b0 50 FUNC GLOBAL DEFAULT 11 _ZN16DeskbarReplicantC2EP8BMessage
257: 00000000000057f0 207 FUNC GLOBAL DEFAULT 11 _ZN16DeskbarReplicant11InstantiateEP8BMessage
Here’s instead the output generated from the full C++ add on without the huiku.c compiled:
20: 0000000000000000 0 FILE LOCAL DEFAULT ABS DeskbarReplicant.cpp
139: 0000000000006232 158 FUNC GLOBAL DEFAULT 11 _ZN16DeskbarReplicantC2E5BRecti
150: 0000000000009230 24 OBJECT WEAK DEFAULT 19 _ZTI16DeskbarReplicant
152: 0000000000006334 45 FUNC GLOBAL DEFAULT 11 _ZN16DeskbarReplicantD2Ev
171: 0000000000009020 528 OBJECT WEAK DEFAULT 19 _ZTV16DeskbarReplicant
172: 0000000000006362 43 FUNC GLOBAL DEFAULT 11 _ZN16DeskbarReplicantD0Ev
175: 0000000000006bea 169 FUNC GLOBAL DEFAULT 11 _ZN16DeskbarReplicant15_ForwardMessageEPKcP8BMessage
184: 000000000000677e 160 FUNC GLOBAL DEFAULT 11 _ZN16DeskbarReplicant16AttachedToWindowEv
190: 0000000000006232 158 FUNC GLOBAL DEFAULT 11 _ZN16DeskbarReplicantC1E5BRecti
191: 00000000000072a4 1598 FUNC GLOBAL DEFAULT 11 _ZN16DeskbarReplicant27_SendComposeMessageShortcutEv
208: 000000000000681e 320 FUNC GLOBAL DEFAULT 11 _ZN16DeskbarReplicant4DrawE5BRect
217: 000000000000695e 246 FUNC GLOBAL DEFAULT 11 _ZN16DeskbarReplicant15MessageReceivedEP8BMessage
241: 0000000000008480 19 OBJECT WEAK DEFAULT 13 _ZTS16DeskbarReplicant
242: 00000000000066fa 131 FUNC GLOBAL DEFAULT 11 _ZNK16DeskbarReplicant7ArchiveEP8BMessageb
254: 00000000000062d0 100 FUNC GLOBAL DEFAULT 11 _ZN16DeskbarReplicantC1EP8BMessage
328: 0000000000006b68 129 FUNC GLOBAL DEFAULT 11 _ZN16DeskbarReplicant25_LaunchApplicationAndWaitEPKc
337: 0000000000006aa0 199 FUNC GLOBAL DEFAULT 11 _ZN16DeskbarReplicant23_QuitApplicationAndWaitEPKc
343: 0000000000006a54 76 FUNC GLOBAL DEFAULT 11 _ZN16DeskbarReplicant5PulseEv
378: 0000000000006334 45 FUNC GLOBAL DEFAULT 11 _ZN16DeskbarReplicantD1Ev
379: 000000000000638e 696 FUNC GLOBAL DEFAULT 11 _ZN16DeskbarReplicant5_InitEv
381: 0000000000006c94 1551 FUNC GLOBAL DEFAULT 11 _ZN16DeskbarReplicant9MouseDownE6BPoint
389: 00000000000062d0 100 FUNC GLOBAL DEFAULT 11 _ZN16DeskbarReplicantC2EP8BMessage
393: 0000000000006646 180 FUNC GLOBAL DEFAULT 11 _ZN16DeskbarReplicant11InstantiateEP8BMessage
There are symbols marked with the suffix .cold, what is that? Could it have to do with the issue of some functions not getting called?
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?