Error adding a deskbar replicant: Name not found

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!

2 Likes

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:

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?

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?