Calling a dylib

Is there a way to call a dylib function from different dylibs?

The standard:

Soft Declare MyDylibFunc Lib libraryname As Integer

The libraryname seems to be required to be a constant. I would like to supply a variable library name.

Is this possible?

If the library name is known at compile-time then you can probably work something out using condition compilation.

If it’s not known until runtime then this can only be accomplished by writing a custom library loader. I wrote this loader as a proof-of-concept a while ago. It’s Windows only, but it might give you some ideas if you decide to write one for Mac (but that’s kind of a drastic solution to your problem.)

Thank you for the information.

I do not know the name of the library at compile time, this is the reason I am looking for a way to load the library at run-time.

I have downloaded your loader. I appreciate that it is for Windows but I will work through it to see if I can use something similar for MacOS.

The main reason that I need this function is that I have the concept of a dynamically driven system where users of the system can create their own delis (with a fixed entry point [process name]) but does something different. For example, I have a dylib called simon.dylib with one external procedure called ‘RunMe’. The ‘normal’ declare would be:

Soft Declare Sub RunMe lib "simon.dylib"

The user of the system determines that he needs the RunMe procedure to do something else so he creates a dylib called simonExtended.dylib that does something else. His declaration would look like this:

Soft Declare Sub RunMe lib "simonExtended.dylib"

Once compiled in to a dylib all he has to do is place the dylib in the dylibs folder and set a new item in a database table that the main call would now route to simonExtended.dylib.

So, what I really need is something like this:

Sub RunSimon (libName As String) Soft Declare Sub RunMe Lib libName RunMe end Sub
Having had a brief look at your loader this seems to be the way to go - unless you have any other suggestions.

Thanks so far.

Simon.

You might find Delegates 101 on http://www.xdevlibrary.com useful.

If you don’t have the name of the library until runtime, you can use our SoftDeclareMBS class in MBS Xojo Plugins.
That was implemented long ago before we had soft declares in Xojo, but is still useful.

Thank you, Christian, but I don’t want to use a plugin. This is because the app I am creating will be a commercial app and I have to release source code. It has to be pure Xojo.

I don’t see why there is this limitation, why can’t I call a library named by a variable?

You can use plugins and release source code.
That is not a problem.

Because the dylibs are hard-linked, i.e. they get loaded by the OS loader when the program loads, before the code runs.

There is another way: With the macOSlib you can load dylibs (or bundles, at least) and then look up functions in it, get their address, then use “new delegate (theAddress)” to be able to invoke them.

Don’t have have any code ready, but be sure to seek non-Xojo answers in the web about that, then see what macosLib offers.

Aren’t soft declares resolved on first use?

Well, now you got me wondering, too. But I think we had this issue discussed before here in the forum, and that the thing was that the lib ref is always hard-coded and prelinked, but the method lookup is only done when used. Also, IIRC, when you address objc messages, not C functions, then the dylib name doesn’t even matter, and you can simply load the framework manually, and then use a declare with a random lib name, as you will do all lookups (such as for the class name) dynamically anyway, no matter in which lib they appear (they call share a global name pool, which gets set up when you load the frameworks).

I bought the Delegates 101 book from xdevlibrary. The book describes what Thomas has suggested. I thought that this was the answer but found that it did not work after creating a test project.

I noticed within the book (and noted by Thomas - shown above) that the dylib should be created as a CFBundle. I am not using Xcode to create the dylib and this could be the issue. Is there a way to use a ‘standard’ dylib either created outside of Xcode or a dylib where the provenance is unknown?

Look at UnicodeFormsExtension - that’s a class in macosLib, or google for it. Basically, you’d load a dylib with dlopen(), then look up its address with dlsym().

Solved!

I really could not get my head around the suggestions here and did not want to introduce any plugins or macos lib (I think it is still 32 bit but am not sure). So, I looked at my dylib development tool and found that the way in which it handles dylibs is exactly what I was looking for. It loads the dylib, finds the function and maps it to a procedure that is then executed.

I have created a ‘master’ dylib that does all the switching and calling from within. This ‘master’ is then called by my Xojo app that just sends the dylib name and function to the ‘master’ that actually does the work. It works fine and has solved my problem.

Again, I would like to thank all who contributed. As normal, when I have a problem and ask here I get great responses that push me to find a solution. Lovely people.

Simon.

Congrats. So, you wrote the part that resolves the dylib in C, not Xojo, right? Did you use dlopen and dlsym to look up the function, as I suggested?

No, the macoslib is 32 bit and I need 64 bit.

In Xojo I have just used the standard declaration to my master function. I send which dylib to use to the master and my master dylib loads the target dylib and executes the procedure. Xojo never directly calls the unresolved dylib, the master dylib resolves this and returns the target dylib’s return value(s).

Actually I am not using C. The best tool I have found for creating 64 bit dylibs is PureBasic. This is the development environment that I really like and it creates really fast and small dylibs. I use Xojo for all the main app development but had a need to create an app that can have hooks without recompiling the main app. This was the reason for my original question.

Having a master dylib with just one target dylib allows me to deliver the app and the client can extend the functionality by just creating more target dylibs in whatever language they prefer. They only have to add the name of the newly created dylib to an internal app table within the database and the app can resolve to the new target with no recompilation of the Xojo app.

The client will only need me if they wish to add previously unknown functionality to the app. Existing functionality can be created by themselves.

Simon.