Shared Library in PhAp.

Hi, I would like to create a shared library from PhAB and link this
shared library to another PhAB application so that I can develop GUI
upgrades through shared libraries to avoid compiling and linking
everytime there is a software upgrades. For example, if I load
version.so.1 it give one type of interface from loading version.so.2.


I have just found out that you can use this “addvariant” script
command in QNX to make DLL (.so) out of a PhAB application. But after
making the DLL I don’t know how I can interact with this library (link
to my other Main PhAB app). Such as what functions to call to
display the new GUI in that DLL…

Any idea?

jinma <matthew.jin@fmcti-dot-com.no-spam.invalid> wrote:

Hi, I would like to create a shared library from PhAB and link this
shared library to another PhAB application so that I can develop GUI
upgrades through shared libraries to avoid compiling and linking
everytime there is a software upgrades. For example, if I load
version.so.1 it give one type of interface from loading version.so.2.



I have just found out that you can use this “addvariant” script
command in QNX to make DLL (.so) out of a PhAB application. But after
making the DLL I don’t know how I can interact with this library (link
to my other Main PhAB app). Such as what functions to call to
display the new GUI in that DLL…

dlopen()
dlsym()

If you are going to be explicitly loading the shared object.

If you’re not going to be explicitly loading the shared object, you
should be able to just link against the .so as if it were a standard
(.a) library, and it should “just work”.

What I don’t know is how this will interact with phabbind, which stores
info in the program file as elf records.

-David

David Gibbs
QNX Training Services
dagibbs@qnx.com

David Gibbs wrote:

jinma <> matthew.jin@fmcti-dot-com.no-spam.invalid> > wrote:

Hi, I would like to create a shared library from PhAB and link this
shared library to another PhAB application so that I can develop GUI
upgrades through shared libraries to avoid compiling and linking
everytime there is a software upgrades. For example, if I load
version.so.1 it give one type of interface from loading version.so.2.

I have just found out that you can use this “addvariant” script
command in QNX to make DLL (.so) out of a PhAB application. But after
making the DLL I don’t know how I can interact with this library (link
to my other Main PhAB app). Such as what functions to call to
display the new GUI in that DLL…

If you’re not going to be explicitly loading the shared object, you
should be able to just link against the .so as if it were a standard
(.a) library, and it should “just work”.

Umm… Sorry, but no. There are a number of variables with fixed names
that PhAB generates in every application, such as “AbContext”,
“AbWidgets”, and so on. For the PhAB stuff to work, the code in your
DLL must use the variables defined in the DLL, and the code in the main
application must use the variables defined in the application. The only
supported way to achieve that is by linking the DLL with the -Bsymbolic
option, and by using dlopen() to load it.

(Another possible way is to rename PhAB’s internal variables in the DLL
using the C preprocessor – that’s the only way that allows a static .a
library rather than a DLL. I tried that a while ago and it worked, but
it requires more knowledge about PhAB’s internal details that the docs
offer, may stop working in the next release, and, like I said, it’s not
supported.)

Also, before doing any PhAB stuff in the DLL, you must register the
DLL’s “PhAB context” by passing the address of the DLL’s ApContext
variable and the DLL’s pathname to ApAddContext(). Take a look at the
“Making a DLL out of a PhAB application” section in the Programmer’s
guide for more details.

(Oh, and keep in mind that the DLL’s main() does not run (and you
shouldn’t try to call it, either!). This means that any initialization
function you define in PhAB will not be called for you, and any “base
window” you’ve set up as the startup window will not be opened, either.
You’ll have to create it using ApCreateModule().)

What I don’t know is how this will interact with phabbind, which stores
info in the program file as elf records.

Right; that’s also pretty tricky when you want to do a static library.
That’s another reason why its unsupported.

thanks for your answer… I do know about dlopen and dlsym my question
was what function do I need to call once I dlopen() my shared lib.
using dlsym()… do I call dlsym(abmain) to display the GUI that I
made in PhAB ???
Again, I have already designed my GUI using PhAB and made a shared
library out of it using “addvariant” command script. Thanks

jinma wrote:

thanks for your answer… I do know about dlopen and dlsym my question
was what function do I need to call once I dlopen() my shared lib.
using dlsym()… do I call dlsym(abmain) to display the GUI that I
made in PhAB ???

The usual way is that you put a function in the DLL whose name the main
program knows. In that function, you call ApAddContext() as I explained
earlier, and do whatever else you want the DLL to do at initialization.
In the main program, you call dlsym() to obtain the address of the
function, and then call it. More or less like this, except I’d
recommend adding some error checking:

// In the DLL:
int initialize_DLL( const char *path ) {
ApAddContext( &AbContext, path );
initialize_my_stuff();
ApCreateModule( ABM_DLLs_window, … );
return OK;
}

// In the main program:
void handle = dlopen( dllpath, RTLD_NOW | RTLD_LOCAL );
int (fun)(const char) = (int(
)(const char*)) dlsym( handle,
“initialize_DLL” );
(*fun)( dllpath );

Again, I have already designed my GUI using PhAB and made a shared
library out of it using “addvariant” command script. Thanks

Make sure to name the variant “dll” rather than “so” – this will take
care of the -Bsymbolic linker option.

wow~ thanks a lot for your help Lerch, you are better than the QNX
support stuff :slight_smile:
I will do as you have suggested, but before we conclude on this
discussion, I would like to confirm my understanding on this topic.
If you feel that I am missing something please tell me.

My steps of creating DLL out of PhAB and using it.

  1. Create a GUI base window with bunch of stuff (ie menu, buttons
    etc…) also call this base window DLL_window

  2. Create a DLL initialization function as described (with
    ApAddcontext, ApCreatModule(ABM_DLL_window,…);
    Just a question on this part. Can I make this
    initialization from PhAB like this
    a) go to project → properties
    b) in there, you can create setup functions, add global
    header, and Initialization function
    c) type in the initialize_DLL in the Initialization
    function
    d) open the initialize_DLL.c file that PhAB has
    generated and do my initialization routine as described.

  3. Now I have working GUI that has all the widgets I need with all
    the callbacks, and initialization function, and lets say that my work
    is stored in /work/DLL_GUI/

  4. go to /work/ directory and type “addvariant”, which creates teh
    x86.so directory

  5. now I can go to /work/DLL_GUI/x86/x86.so/ which has DLL_GUI.so and
    DLL_GUIS.a and DLL_GUI.a

  • another question here, how come there are three library
    made here? According to you I can only use DLL_GUI.so so
    should I ignor the share static and static library?
  1. Rename DLL_GUI.so to DLL_GUI.dll so that I don’t have to do
    -Bsymbolic linker option

  2. Now we have a GUI shared library ready to be used.

:sunglasses: Create another PhAB application which will just call (dlopen) this
DLL_GUI.dll library

  • just create an base window
  • In the setup function of this base window make a main program
    which will
    a) dlopen the DLL_GUI.dll
    b) declears the function pointers that points to the DLL
    initialization function and assign it using dlsym()
    c) finally calls this DLL initialzation function to
    display the GUI I have created in DLL_GUI.dll

mistake… on step 4, I ment “addvariant x86.so”

“jinma” <matthew.jin@fmcti-dot-com.no-spam.invalid> wrote in message
news:cspgio$2i8$1@inn.qnx.com

wow~ thanks a lot for your help Lerch, you are better than the QNX
support stuff :slight_smile:

Thanks, but that’s a bit unfair. It’s easy for me to explain this stuff
because I designed and implemented it. They have to learn about it the hard
way…

I will do as you have suggested, but before we conclude on this
discussion, I would like to confirm my understanding on this topic.
If you feel that I am missing something please tell me.

My steps of creating DLL out of PhAB and using it.

  1. Create a GUI base window with bunch of stuff (ie menu, buttons
    etc…) also call this base window DLL_window
  2. Create a DLL initialization function as described (with
    ApAddcontext, ApCreatModule(ABM_DLL_window,…);
    Just a question on this part. Can I make this
    initialization from PhAB like this
    a) go to project → properties

No. The initialization function and setup function in there are what main()
runs at startup. Your DLL will not execute its main(). Instead, you need
to go to Project → Internal links, create an internal link for your window,
and specify the setup function there. ApCreateModule() needs an internal
link.

b) in there, you can create setup functions, add global
header, and Initialization function

The global header, OK. The other two, no.

c) type in the initialize_DLL in the Initialization
function

No, that would generate a prototype for initialize_DLL that’s incompatible
with how you want to define the function. Your function has nothing to do
with what PhAB thinks of as “the” Initialization function. PhAB’s
Initialization function is what the PhAB-generated main() uses to parse the
command-line arguments. Your DLL will not run its main, and won’t have any
command-line arguments to parse.

d) open the initialize_DLL.c file that PhAB has
generated and do my initialization routine as described.

Just write your initialize_DLL function by hand. Add it to the source file
that has your setup function in it. Or to some other source file, it
doesn’t matter. PhAB doesn’t need to know about your function. PhAB
doesn’t even need to know that you’re creating a DLL rather than an
application. That’s why PhAB keeps generating a main() for you. But that’s
not a problem. Just don’t make it unnecessarily large by adding PhAB
initialization functions and setup modules…

  1. Now I have working GUI that has all the widgets I need with all
    the callbacks, and initialization function, and lets say that my work
    is stored in /work/DLL_GUI/

  2. go to /work/ directory and type “addvariant”, which creates teh
    x86.so directory

No, go to /work/DLL_GUI and type “addvariant dll”, which should create the
x86/dll directory.

  1. now I can go to /work/DLL_GUI/x86/x86.so/ which has DLL_GUI.so and
    DLL_GUIS.a and DLL_GUI.a
  • another question here, how come there are three library
    made here? According to you I can only use DLL_GUI.so so
    should I ignor the share static and static library?

If you do it my way, it shouldn’t create the .a’s.

  1. Rename DLL_GUI.so to DLL_GUI.dll so that I don’t have to do
    -Bsymbolic linker option

Rename it if you want, but since it’s been linked already, it’s too late to
change the linker option. If you specify “dll” to addvariant, you’ll see
the -Bsymbolic option when make builds DLL_GUI.so.

  1. Now we have a GUI shared library ready to be used.

:sunglasses: > Create another PhAB application which will just call (dlopen) this
DLL_GUI.dll library

  • just create an base window
  • In the setup function of this base window make a main program
    which will
    a) dlopen the DLL_GUI.dll
    b) declears the function pointers that points to the DLL
    initialization function and assign it using dlsym()
    c) finally calls this DLL initialzation function to
    display the GUI I have created in DLL_GUI.dll

Do you need to ever unload the DLL before the main application exits? If
you do, that’s another big topic…

Thanks again for your support. I didn’t mean to put down the support
stuff by any means… sorry if that has offended you. And Yes, I
think it would be good idea to unload the DLL to do some clean ups
before the main application exits.
Is there any critical issus here that I should pay attention to?
I know that I have to

  • close any widget databases that my dll opened
  • destory PhAB link callbacks defined in teh DLL, ApCreatedModule()
  • and ApRemoveContext an all ApAddContext I have called.

jinma wrote:

Thanks again for your support. I didn’t mean to put down the support
stuff by any means… sorry if that has offended you. And Yes, I
think it would be good idea to unload the DLL to do some clean ups
before the main application exits.
Is there any critical issus here that I should pay attention to?
I know that I have to

  • close any widget databases that my dll opened

… and free any other stuff that the main program doesn’t know how to
free…

  • destory PhAB link callbacks defined in teh DLL, ApCreatedModule()

The goal here is to make sure that you don’t have any widgets left whose
callbacks may want to access some data or code in the DLL. The safest
way is to destroy any widgets that the DLL has created, and remove any
callbacks it has attached to the main app’s widgets. If you need some
of the widgets created by the DLL to survive the unload, that can be a
little tricky. But hopefully you don’t.

  • and ApRemoveContext an all ApAddContext I have called.

… and finally call dlclose() from the main program. That can be
tricky if you want the DLL to decide when to get unloaded. For
instance, imagine that the DLL has an “Unload me” button in one of its
dialogs. You can’t call dlclose() from the button’s callback – you
need to wait until after the callback has returned. Registering a
workproc is often a safe way, but the workproc must be a function in the
main program rather than in the DLL.

thanks a bunch for all your help~