Author Topic: Make functions of one program available for other programs?  (Read 7033 times)

0 Members and 1 Guest are viewing this topic.

Offline compu

  • LV5 Advanced (Next: 300)
  • *****
  • Posts: 275
  • Rating: +63/-3
    • View Profile
Make functions of one program available for other programs?
« on: August 22, 2011, 03:56:41 pm »
When I launch a program via my shell, is it possible to make functions and variables of it available for the launched program?

Offline ExtendeD

  • CoT Emeritus
  • LV8 Addict (Next: 1000)
  • *
  • Posts: 825
  • Rating: +167/-2
    • View Profile
Re: Make functions of one program available for other programs?
« Reply #1 on: August 22, 2011, 04:25:03 pm »
Sharing functions dynamically would require dynamic libraries, which is not supported and not really planned in Ndless. But these functions can also be exported as a static library, bound with the program launched at compile time (see how libndls is built and used or bwang's C library somewhere on Omnimaga).

Sharing variables would require a Shared memory, I don't know if the TI-Nspire includes anything like this. A dirty workaround would be to pass the address of a memory block allocated by the shell to the programs launched as a command line parameter, and access the variables relatively to this base address. This could also be used to call back dynamically functions from the shell by the way.
Ndless.me with the finest TI-Nspire programs

Offline compu

  • LV5 Advanced (Next: 300)
  • *****
  • Posts: 275
  • Rating: +63/-3
    • View Profile
Re: Make functions of one program available for other programs?
« Reply #2 on: August 24, 2011, 02:42:06 pm »
I've tried it on this way now:

I define a structre called _rshellAPI (in a header file that is included in rshell and the launched program) which looks like this:
Code: [Select]
typedef struct _rshellAPI
{
void (*c_draw)(void);
void (*c_clear)(void);
void (*c_writec)(char ch);
void (*c_write)(char* str);
void (*c_swrite)(char* format, int buflen, ...);

char (*cn_readc)(void);
char (*c_readc)(void);

int (*c_read)(char* str);
} rshellAPI;

In rshell's source, I initialize this structure with functions of Nspire I/O:
Code: [Select]
rshellAPI rshell =
{
&c_draw,
&c_clear,
&c_writec,
&c_write,
&c_swrite,
&cn_readc,
&c_readc,
&c_read
};

And then pass it to the launched program:
Code: [Select]
((void (*)(int, char **, rshellAPI*))(docptr + sizeof(PRGMSIG)))(n_argc, n_argv, &rshell);
Then I've changed the launched program to use these functions:

Code: (main() definition) [Select]
int main(int argc, char** argv, rshellAPI* rshell)
Code: (example call) [Select]
rshell->c_writec('\n');

All this compiles without errors, but when the launched program tries to call one of the functions, this happens:
Code: [Select]
Error at PC=11140B6C: Unaligned read_word: 11
        Backtrace:
Frame     PrvFrame Self     Return   Start
11136665: 41000000 3A41003A 003E7325 000A0D20
41000000: invalid address

What is wrong with this?
« Last Edit: August 24, 2011, 02:59:22 pm by compu »

Offline ExtendeD

  • CoT Emeritus
  • LV8 Addict (Next: 1000)
  • *
  • Posts: 825
  • Rating: +167/-2
    • View Profile
Re: Make functions of one program available for other programs?
« Reply #3 on: August 24, 2011, 04:46:55 pm »
Does it crash before the call or within the function called?
Ndless.me with the finest TI-Nspire programs

Offline bsl

  • LV4 Regular (Next: 200)
  • ****
  • Posts: 157
  • Rating: +14/-0
    • View Profile
Re: Make functions of one program available for other programs?
« Reply #4 on: August 24, 2011, 07:16:29 pm »
Try isolating the problem, see if what you passed is getting there.
They should match.

from the launcner:
printf("n_argc=%i, n_argc=%p, &rshell=%X\n",n_argc, n_argv, &rshell);
((void (*)(int, char **, rshellAPI*))(docptr + sizeof(PRGMSIG)))(n_argc, n_argv, &rshell);


from the launcned:
int main(int argc, char** argv, rshellAPI* rshell){
 printf(argc=%i, argv=%p, rshell=%p\n",argc, argv, rshell);
.
.
.
}

Alignment errors: The adressess in argv, rshell should end in: 0,4,8,C


Declaring with "static" might solve the alignment problem:
static rshellAPI rshell =
{
   &c_draw,
   &c_clear,
   &c_writec,
   &c_write,
   &c_swrite,
   &cn_readc,
   &c_readc,
   &c_read
};

Offline calc84maniac

  • eZ80 Guru
  • Coder Of Tomorrow
  • LV11 Super Veteran (Next: 3000)
  • ***********
  • Posts: 2912
  • Rating: +471/-17
    • View Profile
    • TI-Boy CE
Re: Make functions of one program available for other programs?
« Reply #5 on: August 24, 2011, 07:29:57 pm »
Do function pointers work properly in the Ndless toolchain? I remember they didn't at some point. What are the GCC options in your makefile?
"Most people ask, 'What does a thing do?' Hackers ask, 'What can I make it do?'" - Pablos Holman

Offline bsl

  • LV4 Regular (Next: 200)
  • ****
  • Posts: 157
  • Rating: +14/-0
    • View Profile
Re: Make functions of one program available for other programs?
« Reply #6 on: August 24, 2011, 07:40:41 pm »
Yes, they do.
Look at  ploaderhook.c

Offline ExtendeD

  • CoT Emeritus
  • LV8 Addict (Next: 1000)
  • *
  • Posts: 825
  • Rating: +167/-2
    • View Profile
Re: Make functions of one program available for other programs?
« Reply #7 on: August 25, 2011, 02:24:41 am »
Do function pointers work properly in the Ndless toolchain? I remember they didn't at some point. What are the GCC options in your makefile?

Wait, you're right, I forgot that one: http://hackspire.unsads.com/wiki/index.php/Ndless_features_and_limitations#Global_variables
You should use nl_relocdata() on your functions array.
Ndless.me with the finest TI-Nspire programs

Offline compu

  • LV5 Advanced (Next: 300)
  • *****
  • Posts: 275
  • Rating: +63/-3
    • View Profile
Re: Make functions of one program available for other programs?
« Reply #8 on: August 25, 2011, 07:33:30 am »
First of all, thanks for your help.
Currently I'm not at home, but how do I have to call nl_relocdata() with a structure?
What is the first argument (nl_relocdata_data on Hackspire)?

Offline compu

  • LV5 Advanced (Next: 300)
  • *****
  • Posts: 275
  • Rating: +63/-3
    • View Profile
Re: Make functions of one program available for other programs?
« Reply #9 on: August 30, 2011, 01:25:33 pm »
BUMP

Code: (Launcher) [Select]
n_argc=1, n_argv=1800e070, &rshell=111B0400
Code: (Launched) [Select]
argc=1, argv=1800e070, rshell=00000001

Offline bsl

  • LV4 Regular (Next: 200)
  • ****
  • Posts: 157
  • Rating: +14/-0
    • View Profile
Re: Make functions of one program available for other programs?
« Reply #10 on: August 30, 2011, 08:20:03 pm »
Try this:
Instead of passing a third argument, just use the last n_argv[19]
to pass the rshell address.
Launcher
Code: [Select]
n_argv[19] = (char*)&rshell; // put pointer in last array slot
Launched
Code: [Select]

int main(int argc, char** argv){
 rshellAPI *rshell;
  rshell = (rshellAPI *)argv[19];
.
.
.
}


Offline compu

  • LV5 Advanced (Next: 300)
  • *****
  • Posts: 275
  • Rating: +63/-3
    • View Profile
Re: Make functions of one program available for other programs?
« Reply #11 on: August 31, 2011, 02:04:12 am »
Doesn't work, but at least the address of rshell in the launched program isn't 00000001 anymore  :-\

I got 2 different errors and one time it just restarted.

Code: (Adresses of argv 19) [Select]
Launcher: 1800e93c
Launched: 111793a8

Offline ExtendeD

  • CoT Emeritus
  • LV8 Addict (Next: 1000)
  • *
  • Posts: 825
  • Rating: +167/-2
    • View Profile
Re: Make functions of one program available for other programs?
« Reply #12 on: September 12, 2011, 01:59:45 pm »
First of all, thanks for your help.
Currently I'm not at home, but how do I have to call nl_relocdata() with a structure?
What is the first argument (nl_relocdata_data on Hackspire)?

There was a typo in the sample on Hackspire, it's fixed: http://hackspire.unsads.com/wiki/index.php/Ndless_features_and_limitations#Global_variables
The first argument would be rshell in your case.
Ndless.me with the finest TI-Nspire programs