1

I have some mail from somebody else wanting to develop a SVG renderer for HibView. A good idea is to make it as a plugin of HibView : not everybody will need a SVG renderer.
The problem is how to make a plugin interface. I want to evaluate all possibilities. I don't know the kernel world, but in the nostub world, it seems to be impossible, isn't it ?

2

No, it's not impossible.
It may be easier in kernel mode, though.
avatar« Quand le dernier arbre sera abattu, la dernière rivière empoisonnée, le dernier poisson capturé, alors vous découvrirez que l'argent ne se mange pas. »

3

Can you explain ? Or give some links ?

4

nostub DLL can be a way to do (and can give you some informations)
avatarProud to be CAKE©®™


GCC4TI importe qui a problème en Autriche, pour l'UE plus et une encore de correspours nucléaire, ce n'est pas ytre d'instérier. L'état très même contraire, toujours reconstruire un pouvoir une choyer d'aucrée de compris le plus mite de genre, ce n'est pas moins)
Stalin est l'élection de la langie.

5

I forgot to say that I was thinking about making HibView as a dynamic library, for a game and an explorer which want to draw some formatted text.
Is it possible to call a lib from a lib ?

6

with "official" nostub dll it can't be done.
avatarProud to be CAKE©®™


GCC4TI importe qui a problème en Autriche, pour l'UE plus et une encore de correspours nucléaire, ce n'est pas ytre d'instérier. L'état très même contraire, toujours reconstruire un pouvoir une choyer d'aucrée de compris le plus mite de genre, ce n'est pas moins)
Stalin est l'élection de la langie.

7

plus if you want to support any number of external plugins, out-of-the-box nostub dlls aren't going to work either... (this is so to prevent developers from having ideas such as yours sick)

in my opinion kernel mode would be far simpler, except if you intend to develop a whole dll framework for nostub ^^

8

Pollux :
plus if you want to support any number of external plugins, out-of-the-box nostub dlls aren't going to work either... (this is so to prevent developers from having ideas such as yours sick)
you think that my ideas are crazy ? (as you smiley suggests)
in my opinion kernel mode would be far simpler, except if you intend to develop a whole dll framework for nostub ^^

that's what i was presuming tongue
I will take a look to the kernel world ^^

9

hibOu
: you think that my ideas are crazy ? (as you smiley suggests)

No, my smiley was targetted at the not-so-anynomous TIGCC maintainer who wants to prevent programmers from implementing a plugin system just because he thinks it's a bad idea tripaf

Of course I, for one, think it's a good idea (though I doubt of the efficiency of the SVG format itself: XML was not designed to be compact or efficient, it was designed to be human-readable; thus it would be a good idea to at least use a different encoding for XML, or even switch to a binary, space-efficient format such as Flash -- IIRC it is a documented standard, much like PDF, so it might be worth considering smile)

10

Pollux
:
hibOu
: you think that my ideas are crazy ? (as you smiley suggests)

No, my smiley was targetted at the not-so-anynomous TIGCC maintainer who wants to prevent programmers from implementing a plugin system just because he thinks it's a bad idea tripaf
ok grin
Of course I, for one, think it's a good idea (though I doubt of the efficiency of the SVG format itself: XML was not designed to be compact or efficient, it was designed to be human-readable; thus it would be a good idea to at least use a different encoding for XML, or even switch to a binary, space-efficient format such as Flash -- IIRC it is a documented standard, much like PDF, so it might be worth considering smile)
yes, I agree.
In fact I don't know how he serialized his SVG files.
And that's why make it as a plugin is for me a good idea. There is just the question of technical feasibility.

11

Well, maybe deflated XML could work. As it's text-only, compressing XML is quite efficient, even with simple compression schemes.

The whole point about SVG is that it is standard and both human and machine-readable. If you are to make a modified / binary version, you loose most of its key features, the modified version being nor standard nor human-readable.
If you don't care about that, you would better be going after another format, like Pollux suggests. You can even build your own, as long as you provide easy ways to convert to and from it.

12

In fact, the SVG in not mine, it the developper's one tongue
My problem is, how to do a plugin interface. all ideas or comment about it are welcomed wink

13

Well typically you will want to define a set of mandatory function to be exported by a dynamic library
For instance, you define that a valid plugin is a dynamic library that exports a function with the prototype int init_hibview_plugin(.....)

Then, all you have to do to load a plugin is :
- load the library
- locate the init_hibview_plugin function (as it is exported this should be quite easy)
- call the function, giving it all the parameters it may need to be fully functionnal (for instance this could be the address of a table of recognized formats into which the plugin could add itself). You may allow the plugin access to internal functions of the main program, though doing so makes future program evolution more difficult (plugin incompatibility).
- check that the plugin does not fail its initialization

Well that's a bit rough, but the main idea is here. If you want I will work on a fully grown example (I'm working on a set of ti-89 programming examples, and this would be a good candidate), but right now I have to leave so I do not miss an appointment.

14

I thinks he wants a solution for making the plugins, not what to put inside the plugins ^^
avatarProud to be CAKE©®™


GCC4TI importe qui a problème en Autriche, pour l'UE plus et une encore de correspours nucléaire, ce n'est pas ytre d'instérier. L'état très même contraire, toujours reconstruire un pouvoir une choyer d'aucrée de compris le plus mite de genre, ce n'est pas moins)
Stalin est l'élection de la langie.

15

spectras :
Well typically you will want to define a set of mandatory function to be exported by a dynamic library
For instance, you define that a valid plugin is a dynamic library that exports a function with the prototype int init_hibview_plugin(.....)

Then, all you have to do to load a plugin is :
- load the library
- locate the init_hibview_plugin function (as it is exported this should be quite easy)
- call the function, giving it all the parameters it may need to be fully functionnal (for instance this could be the address of a table of recognized formats into which the plugin could add itself). You may allow the plugin access to internal functions of the main program, though doing so makes future program evolution more difficult (plugin incompatibility).
- check that the plugin does not fail its initialization

Ok, as I thought a plugin is a particular type of dynamique lib.
But I have some questions (I didn't read any doc yet about kernel libs...)
- as I can "transmit" pointers on datas from the main code to the plugin (and the reverse), can I transmit pointers of function and execute them ? (I don't think I need it, but I'm curious)
- can I load several libraries ? if yes, are the function namespace separated ? (there won't be confusion between the init_plugin function form the svg plugin and the init_plugin function from the fash plugin (just a example grin))
- can I call a library from a library ?
Well that's a bit rough, but the main idea is here. If you want I will work on a fully grown example (I'm working on a set of ti-89 programming examples, and this would be a good candidate), but right now I have to leave so I do not miss an appointment.

examples are always welcomed wink

16

- as I can "transmit" pointers on datas from the main code to the plugin (and the reverse), can I transmit pointers of function and execute them ? (I don't think I need it, but I'm curious)
You can. Although if the dynamic linking is done correctly that should not be necessary since the plugin should have access to all the functions of the program (check this, it is true on all desktop OS, but it may not be on ti89; PpHd should know more about this).

Still, passing function pointers can also be a deliberate choice, as it can be useful for backward compatibility with old plugins in future versions. I would avoid doing that, still.
- can I load several libraries ? if yes, are the function namespace separated ? (there won't be confusion between the init_plugin function form the svg plugin and the init_plugin function from the fash plugin (just a example grin))
Yes you can. And there is no such thing as namespace confusion since dynamically loaded libraries functions cannot be directly referred to in your code. That is you cannot write
/* assumes library foo has a  void myfunction(char * message) */
loadlibrary("foo");
myfunction("hello");
This would create either a linking error or a load-time symbol resolution, neither of which is what you want.

Instead you would write
typedef void (*myfunction_type)(char * message);

foohandle = loadlibrary("foo");
myfunction_address = (myfunction_type) getaddress(foohandle, "myfunction");
(*myfunction_address)("hello");

This explicitly loads the library, look for the "myfunction" symbol then runs it.
- can I call a library from a library ?
It works on all desktop OS. I guess it also works with kernels such as PreOS, though you should test it or ask PpHd to be sure.
examples are always welcomed wink
Unfortunately I'm very busy at the moment and that should last until monday. I hope you're not in a hurry if you choose to wait for a working example happy


Errrh, before you go and try and get a headache about it : the two samples above are only kind of a pseudo code, they are not real function names or anything. If you want to have a look at a fully working example of the concept, this dlopen example does exactly that (it runs on GNU/Linux).

17

spectras
:
- can I load several libraries ? if yes, are the function namespace separated ? (there won't be confusion between the init_plugin function form the svg plugin and the init_plugin function from the fash plugin (just a example grin))
Yes you can. And there is no such thing as namespace confusion since dynamically loaded libraries functions cannot be directly referred to in your code. That is you cannot write
/* assumes library foo has a  void myfunction(char * message) */
loadlibrary("foo");
myfunction("hello");
This would create either a linking error or a load-time symbol resolution, neither of which is what you want.

Instead you would write
typedef void (*myfunction_type)(char * message);

foohandle = loadlibrary("foo");
myfunction_address = (myfunction_type) getaddress(foohandle, "myfunction");
(*myfunction_address)("hello");
This explicitly loads the library, look for the "myfunction" symbol then runs it.
Ok, it looks like very simple, I don't know why I was thinking about a much more complex call...
- can I call a library from a library ?
It works on all desktop OS. I guess it also works with kernels such as PreOS, though you should test it or ask PpHd to be sure.
ok
!invok PpHd
examples are always welcomed wink
Unfortunately I'm very busy at the moment and that should last until monday. I hope you're not in a hurry if you choose to wait for a working example happy
Don't worry about it, I work on HibView in a very sporadic way tongue
Errrh, before you go and try and get a headache about it : the two samples above are only kind of a pseudo code, they are not real function names or anything. If you want to have a look at a fully working example of the concept, this dlopen example does exactly that (it runs on GNU/Linux).
Thank you, I will look at it

18


You can. Although if the dynamic linking is done correctly that should not be necessary since the plugin should have access to all the functions of the program (check this, it is true on all desktop OS, but it may not be on ti89; PpHd should know more about this).


Well, you can. You just have to export in the main program the functions, and then import in the plugin.
All the exported functions/variables must have a name which looks like hibview__NNNN.
Where NNNN is the hexadecimal number of the exported function/variable.
To import it, just declare the function inside the plugin, just like any other function/variable. That's all.

[note]
One Unix world, Shared Linkers act exactly like static linker, ie. it uses a table of current exported symbols (symbol are refered
by string name), and when a new "object file" is loaded in the memory, all the import reference of this new object file is
solved by first checking if the symbol already exists in the current table, otherwise by looking if it is in another "shared object
file". Quite complex, very powerful, but it slows down the program a few.
On the contrary, Kernel import / export only works with "LIBNAME" + NUM. It doesn't slow down your program,
but it is less flexible (You have to rename your symbol to match the form LIBNAME__HNUM).
[/note]

The static library when it sees an import reference to a symbol of the form "LIBNAME__HNUM", first tries to resolve it inside
the current symbols, otherwise tries to look inside the static libraries. And finally, otherwise, it puts it as an import reference in
the Kernel Program. A Kernel Program can perfectly export functions/variables just like libraries.

typedef void (*myfunction_type)(char * message);
foohandle = loadlibrary("foo");
myfunction_address = (myfunction_type) getaddress(foohandle, "myfunction");
(*myfunction_address)("hello");
This explicitly loads the library, look for the "myfunction" symbol then runs it.

Or in Kernel code:
 LibRef *foo = kernel__LibsBegin ("foo", 1); // Load version 1 of library foo
 myfunction = kernel__LibsPtr (foo, 0);   // Function 0 of library foo
 (&myfunction) ("Hello");
 kernel__LibsEnd (foo);

or simpler:
 LibRef *foo = kernel__LibsBegin ("foo", 1); // Load version 1 of library foo
 kernel__LibsCall (foo, 0, "Hello");   // Call Function 0 of library foo
 kernel__LibsEnd (foo);

or even simpler:
 kernel__LibsExec ("foo", 1, 0, "Hello"); // Load library, execute function and close library


Of course the libraries may be packed and compressed too (Using the compression you want).
So a good idea may be to pack the program and the plugin inside only one file. It works very fine cheeky

It works on all desktop OS.

non

I guess it also works with kernels such as PreOS, though you should test it or ask PpHd to be sure.

oui No limit. The plugin may also import at linking time another library.
The used compression may be compressed too, or use another library.
The only limit is that the linking process must be solvable, which shouldn't be a problem.

19

Note that the plugin doesn't need to access hibview using the indirect method (Using kernel calls) but can directly call hibview (Just declare the exported functions like HIBVIEW__HNUM).

20

PpHd :
Or in Kernel code:
 LibRef *foo = kernel__LibsBegin ("foo", 1); // Load version 1 of library foo
 myfunction = kernel__LibsPtr (foo, 0);   // Function 0 of library foo
 (&myfunction) ("Hello");
 kernel__LibsEnd (foo);

or simpler:
 LibRef *foo = kernel__LibsBegin ("foo", 1); // Load version 1 of library foo
 kernel__LibsCall (foo, 0, "Hello");   // Call Function 0 of library foo
 kernel__LibsEnd (foo);

or even simpler:
 kernel__LibsExec ("foo", 1, 0, "Hello"); // Load library, execute function and close library

BTW, you should pay attention to the argument passing convention. For example, if you wish to use kernel__LibsCall, then your convention *has* to be the stkparm convention. Anyway, unless you need better performance, it's a good idea to take stkparm (same convention as TIOS).

21


BTW, you should pay attention to the argument passing convention. For example, if you wish to use kernel__LibsCall, then your convention *has* to be the stkparm convention.


Not really. It works also with mregparm. The only problem is to declare properly the kernel function to push the 2/3 first arguments on the stack, and the others in the registers, without making tigcc cries.

22

> The only problem is to declare properly the kernel function to push the 2/3 first arguments on the stack, and the others in the registers, without making tigcc cries.
FMI, are kernel core functions really different from "usual" functions ? The calling conventions of most ExtGraph grayscale functions is a mix of __regparm__ (d0-d3/a0-a1) and __stkparm__ (the rest), and they're defined in a very simple way I never saw TIGCC complaining about.
avatarMembre de la TI-Chess Team.
Co-mainteneur de GCC4TI (documentation en ligne de GCC4TI), TIEmu et TILP.
Co-admin de TI-Planet.

23

PpHd :
Not really. It works also with mregparm. The only problem is to declare properly the kernel function to push the 2/3 first arguments on the stack, and the others in the registers, without making tigcc cries.

I don't see what you mean, could you be clearer? Of course I did not mean that your whole program had to be stkparm, just that the function you want to export has to be stkparm. (thanks to __attribute__((stkparm)))

24


FMI, are kernel core functions really different from "usual" functions ? The calling conventions of most ExtGraph grayscale functions is a mix of __regparm__ (d0-d3/a0-a1) and __stkparm__ (the rest), and they're defined in a very simple way I never saw TIGCC complaining about.

I don't see what you mean, could you be clearer? Of course I did not mean that your whole program had to be stkparm, just that the function you want to export has to be stkparm. (thanks to __attribute__((stkparm)))


The problem : it is the same function from a C compiler, but with different parameters. So a a declaration with incomplete list of argument is the best solution '...'. You can also give the arguments inside the registers (the Kernel function doesn't destroy them) but I don't know how to declare a function with an incomplete list of arguments using registers to pass the parameters.
In clear: you can use mregparm, but it will be a nightmare. So use stkparm instead.

25

PpHd :
The problem : it is the same function from a C compiler, but with different parameters. So a a declaration with incomplete list of argument is the best solution '...'.

If you do so, it will automatically switch to stkparm (at least that's what GTC does), so there's basically no point in doing that confus (it just makes things more obscure, because you never actually use those extra arguments, and less fool-proof, because extra arguments to the function will be silently ignored)

26


In clear: you can use mregparm, but it will be a nightmare. So use stkparm instead.

27

But declaring a variable-argument function means that it will NOT be a regparm function, so it's actually more than a nightmare: it's NOT possible to do so with regparm tongue (what you were suggesting was really just another way to declare a function as stkparm)

28


It's NOT possible to do so with regparm

It is cheeky

void f (const char *name, char version, char num, int toto asm("d0")) asm ("kernel__0000");
void g (const char *name, char version, char num, int *toto asm("a0")) asm ("kernel__0000");

int h(int *name, int toto)
{
  f ("totoland", 1, 0, toto);
  g ("totoland", 1, 1, name);
}


is assembled in

        .globl  h
h:
        link.w %a6,#0
        move.l %a2,-(%sp)
        subq.l #4,%sp
        clr.b 3(%sp)
        move.b #1,1(%sp)
        pea .LC0
        lea kernel__0000,%a2
        move.w 12(%a6),%d0
        jbsr (%a2)
        subq.l #4,%sp
        move.b #1,3(%sp)
        move.b #1,1(%sp)
        pea .LC0
        move.l 8(%a6),%a0
        jbsr (%a2)
        move.l -4(%a6),%a2
        unlk %a6
        rts

29

I don't know what you're trying to show here, plus it seems you're using stkparm anyway what

30

I have done what you thought what impossible to do, ie mixing stckparm and regparm in an incomplete argument list function. Just read it more carrefully.