• Create Account

## calling function pointer without typedef

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

14 replies to this topic

### #1 fir   Members

-464
Like
0Likes
Like

Posted 27 May 2014 - 03:51 AM

Once time ago I was using dynamic dll linking ,

Here you obtain a function pointer by name,

You should also typedef this pointer but I was

lazy (those typedefs can be complex ) so i tried

to call it without typedef, something like

FARPROC  SomeImportedFunction  = NULL;

int x = SomeImportedFunction(1,2,3);

Has it (this way of using it) a chance to work?

(I think this is dangerous becouse compiler here has to guess

how to pass arguments and this is not type checked in the case

of some omittions or misaligments, wrong arg sizes), but if doing carefully

has this a chance to work, how to do it?

previously i was even unawara I can do this, I mean this way you can

push any arguments configuration then call the pointer, I am not sure how this is working - does it asume SomeImportedFunction is cdecl or stdcall

or what?

(I am not really sure what FARPROC hides, used it becouse it was

simplest not need to define any function pointedr typedef just using some)

### #2Aardvajk  Members

12267
Like
1Likes
Like

Posted 27 May 2014 - 04:09 AM

FARPROC is a typedef:

int (FAR WINAPI * FARPROC) ()

In C, an empty parameter list means "turn off all type checking and pass in whatever I supply". In C++ it means "This method takes no parameters". The C form just makes the assumption that the called function knows what state the stack is in in terms of values that are there. Its more a throwback to the sort of "portable assembler" philosophy of C.

Its not clever to do this though. Far better to cast to a pointer to function typedef that specifies the arguments so the compiler can check you are calling it correctly. If you stuff up, the function will trash all over the stack when it runs.

### #3 fir   Members

-464
Like
0Likes
Like

Posted 27 May 2014 - 04:27 AM

FARPROC is a typedef:

int (FAR WINAPI * FARPROC) ()

In C, an empty parameter list means "turn off all type checking and pass in whatever I supply". In C++ it means "This method takes no parameters". The C form just makes the assumption that the called function knows what state the stack is in in terms of values that are there. Its more a throwback to the sort of "portable assembler" philosophy of C.

Its not clever to do this though. Far better to cast to a pointer to function typedef that specifies the arguments so the compiler can check you are calling it correctly. If you stuff up, the function will trash all over the stack when it runs.

I do not understand (some weak english)

Does this mean that this

FARPROC  SomeImportedFunction  = NULL;

//... obtaint pointer here from dll

int x = SomeImportedFunction(1,2,3);

will work in c but not in c++ or what ? (I usually wrote a c cod e but compile with basic c++ mode, and it seemed 'partially

work' there probably i was passing some wrong size types,

not sure so some worked, some not)

ps

if f() means any arg cann be called , like f(1) , f(1,2,3,4)

how to use it - wrote a definition for this, if args are unknown, i do not understand

Edited by fir, 27 May 2014 - 04:39 AM.

### #4Aardvajk  Members

12267
Like
1Likes
Like

Posted 27 May 2014 - 04:57 AM

Yes, it will work in C but not C++.

In C, a function with no arguments of the form f() can be passed any arguments at all and the compiler just ignores them in terms of checking. To define a C function that takes no arguments, you have to use the form f(void).

In C++ this changed and f() means no arguments. Calling a FARPROC pointer with arguments won't compile on a C++ compiler.

This implies that you, the programmer, are responsible for ensuring that the arguments you pass match whatever the function expects. It also means the compiler can't check that you are passing the correct arguments.

So in the case of loading functions from DLLs, it is far more sensible to create a typedef of a function with the correct arguments. You then only have to get this right in one place, when you cast the return from GetProcAddress, rather than get it right every time you call the resultant function.

Edited by Aardvajk, 27 May 2014 - 04:57 AM.

### #5Bacterius  Members

13100
Like
1Likes
Like

Posted 27 May 2014 - 05:05 AM

If you remove all the winapi crap from the typedef you see that the function pointer FARPROC is defined as:

typedef int (*FARPROC)();


So it is indeed a pointer to a function which takes an indeterminate number of arguments. You can pass in anything you want, the compiler will set up the caller's stack accordingly, and the function will "read" the arguments passed off the stack (this could range from "explodes if you pass the wrong arguments" to "looks at the stack pointer to work out how many arguments were passed, varargs style"). In C, a function which takes exactly zero arguments should normally be written as foo(void).

At least, that is the case in C. As Aardvajk said, C++ deprecates the unspecified argument syntax, so that foo() is effectively equivalent to foo(void), in other words, you will not be able to call the function through the function pointer (or otherwise) with any arguments specified, and your snippet should not work. If it does, it means your C++ compiler is operating in some "C compatibility mode", or that it is simply broken. So for C++ you would presumably need to rewrite the function declaration to explicitly indicate the arguments, or use varargs syntax, and you would probably want to write an idiomatic C++ wrapper on top of it using std::bind or whatever (I don't really know a lot of C++, just saying you would typically write more high level code for this stuff).

FARPROC  SomeImportedFunction  = NULL;
//... obtaint pointer here from dll
int x = SomeImportedFunction(1,2,3);

will work in c but not in c++ or what ? (I usually wrote a c cod e but compile with basic c++ mode, and it seemed 'partially
work' there probably i was passing some wrong size types,
not sure so some worked, some not)

Yes, it will not work in C++. If it work on your compiler, then you're not compiling C++ but C or some hybrid thereof.

if f() means any arg cann be called , like f(1) , f(1,2,3,4)
how to use it - wrote a definition for this, if args are unknown, i do not understand

You as a programmer are supposed to know how to call it. The compiler doesn't know nor care whether the arguments are right or wrong if it's not given a function signature, it will push the arguments into registers/onto the stack following whatever calling convention is in use and will then call the function. If the function can read the arguments (= same calling convention and expected number/format of arguments) then it will work. If not, your program will probably segfault inside the function, or, for some calling conventions, corrupt the stack. This syntax was designed to be very, very close to assembly level, if you don't understand how function calls happen in assembly then you will probably not understand how these types of functions work and why they are relevant. And if you do a lot of C and especially a lot of low-level interop (which it seems you do, seeing your recent posts on static lib compatibility) it would definitely not hurt to take a look.

“If I understand the standard right it is legal and safe to do this but the resulting value could be anything.”

### #6 fir   Members

-464
Like
0Likes
Like

Posted 27 May 2014 - 08:16 AM

FARPROC is a typedef:

int (FAR WINAPI * FARPROC) ()

In C, an empty parameter list means "turn off all type checking and pass in whatever I supply". In C++ it means "This method takes no parameters". The C form just makes the assumption that the called function knows what state the stack is in in terms of values that are there. Its more a throwback to the sort of "portable assembler" philosophy of C.

Its not clever to do this though. Far better to cast to a pointer to function typedef that specifies the arguments so the compiler can check you are calling it correctly. If you stuff up, the function will trash all over the stack when it runs.

alright, tnx, i agrre typedef is far better (I got silent runtime errors indeed), still I am curious;

Some typedefs were hard to obtain as far as i weakly remember ... Does mayby anyone know - If you have a dll

and a header to it , it contains header declarations of functions

... - is there a process of turning this declarations into needed typedefs an easy task, like

int foo();     ->     typedef int (*p_foo) ();

or there I can meet some pitfalls or obstacles I'm vaguelly afraid of?

### #7 fir   Members

-464
Like
0Likes
Like

Posted 27 May 2014 - 08:29 AM

ok, i understand

Yes, it will not work in C++. If it work on your compiler, then you're not compiling C++ but C or some hybrid thereof.

could be i always use c in c++ compiling mode but this was

a small pice and maybe i overlooked to set cpp mode

"You as a programmer are supposed to know how to call it. The compiler doesn't know nor care whether the arguments are right or wrong if it's not given a function signature, it will push the arguments into registers/onto the stack following whatever calling convention is in use and will then call the function. If the function can read the arguments (= same calling convention and expected number/format of arguments) then it will work. If not, your program will probably segfault inside the function, or, for some calling conventions, corrupt the stack. This syntax was designed to be very, very close to assembly level, if you don't understand how function calls happen in assembly then you will probably not understand how these types of functions work and why they are relevant. And if you do a lot of C and especially a lot of low-level interop (which it seems you do, seeing your recent posts on static lib compatibility) it would definitely not hurt to take a look."

i meant if i declare

int f();

how can i use then to use it one time to call like f(1,2)

or other time to call it f(1,2,3)

I can call it any way i like but in definition there is no arguments so how do i then acces to this 1,2 or 1,2,3 values

### #8Aardvajk  Members

12267
Like
1Likes
Like

Posted 27 May 2014 - 08:36 AM

Function typedefs look scary but they are easy enough. Just write it like a function, then put parentheses around the name and put a start in front of the name, then remove parameter names.

double name(int i, const std::string &s);

typedef double (*name)(int, const std::string&);

### #9Aardvajk  Members

12267
Like
1Likes
Like

Posted 27 May 2014 - 08:38 AM

I can call it any way i like but in definition there is no arguments so how do i then acces to this 1,2 or 1,2,3 values

A function would need to do some kind of interogation of the stack to figure out what had been pushed onto the stack prior to the call. Its not possible to do this in standard C and is not a common activity these days.

In the bad old days of C, people were used to working in assembly where they would manage their own stacks, so it was probably far more common back then to mess about with the stack directly in C. There's never really a good reason for that sort of thing in 2014, outside of very niche areas like embedded systems.

Templates, function overloading and inlining in C++ have pretty much removed any need for varadic functions. In C you have the va_args and ellipses system if you really need to mess about.

Edited by Aardvajk, 27 May 2014 - 08:39 AM.

### #10Norman Barrows  Members

6291
Like
1Likes
Like

Posted 27 May 2014 - 12:59 PM

Here's a real world example from Caveman 3.0....

first, the typedefs....

//#################################### TYPEDEFS #####################################################

typedef void functiontype1();

typedef void functiontype2(int);

//#################################### END TYPEDEFS #####################################################


Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php

### #11Norman Barrows  Members

6291
Like
0Likes
Like

Posted 27 May 2014 - 01:05 PM

well, once again the editor is clipping everything after the first "open square bracket, slash, 'code', closed square bracket".

guess i'll have to post the reply in sections...


// action types
struct actionrec
{
char msg[100];
int energy,water_disease,bath_disease;
functiontype1 *proceedure;
int numskills,numparts,numtools,skill[10],xp[10],part[10],partqty[10],tool[10],toolqty[10];
requirementsrec r;
};

actionrec action[maxactions];        // the actions database

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php

### #12Norman Barrows  Members

6291
Like
0Likes
Like

Posted 27 May 2014 - 01:09 PM

Third, forward declaration of the function variables  (you may or may not need forward declarations,depending on the order in which things appear in the source file.....


//################################################# ACTIONS ###################################################

// forward declarations of action routines for init actions database
void drinkliquid();
void _make_object();
void sleep();
void rest();
void bathe();
void restandheal();
void makefire();
void eatfood();                              //   GENERIC      31 foods
void research_skill();                   //   GENERIC      45 skills
void cook_food();                           //   GENERIC      35 cooked foods / liquids
void find_object();                         //   GENERIC    everything you can find
void play_with_fire();
void make_shelter();                        //   GENERIC      6 types of shelters
void demolish_shelter();
void entershelter();
void move();
void inspect_shelter();
void repair_shelter();
void butcher_animal();
void getbone_animal();
void gettrinkets_animal();
void sacrifice_animal();
void skin_animal();
void leaveshelter();
void bathewaterskin();
void forrage();
void fill_waterskins_rain();
void train();                               //   GENERIC      52 types of weapons
void stargaze();
void fill_waterskins();
void swim();
void make_bedding();
void climbtree();
void climbdownfromtree();
void makebedshelter();
void checkbedding();
void fixbedding();
void dance();
void playdrum();
void playflute();
void sing();
void telljoke();
void tellstory();
void fish();
void capture_animal();
void free_animal();
void tame_animal();
void watchclouds();
void fix_object();
void get_tendon_animal();
void make_storepit();
void inspect_storepit();
void repair_storepit();
//void examine_monolith();
void entercave();
void leavecave();
void searchbody();
void learn_from_caveman();
void teach_caveman();
void listen2story();
void teach_bandmember();
void telljokeclan();
void tellstoryclan();
void listen2joke();
void entercavern();
void leavecavern();
void buildpermshel();
void inspectpermshel();
void repairpermshel();
void demolishpermshel();
//void clearrubble();
void make_raft();
void learn_sailing();
void board_raft();
void check_raft();
void repair_raft();
void move_raft();
void disembark();
void pray();
void prayfire();
void poison_wpn();
void apply_camo();
void use_lodestone();
void putoutfire();
void kill_captured();
void make_object2();   // uses reqts rec
void check_trap();
void check_weather();
void check_fire();
void demolish_landmark();
void demolish_bedding();
void inspect_trap();
void repair_world_object();
void demolish_trap();
void inspect_landmark();
void repair_trap();
void daydream();
void talk2friendly();
void talk2bandmember();
void listen2bandmember();


Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php

### #13Norman Barrows  Members

6291
Like
0Likes
Like

Posted 27 May 2014 - 01:14 PM

Fourth, assign the functions to the function varaibles.....



void init_actions_database()
{
ZeroMemory(action,sizeof(actionrec)*maxactions);

action[DONOTHING].energy=1;

strcpy_s(action[DRINK].msg,100,"Drinking...");
action[DRINK].proceedure=drinkliquid;
action[DRINK].water_disease=1;

strcpy_s(action[MAKEOBJ].msg,100,"Making object...");
action[MAKEOBJ].proceedure=_make_object;

action[SLEEP].energy=1;
strcpy_s(action[SLEEP].msg,100,"Sleeping...");
action[SLEEP].proceedure=sleep;

action[REST].energy=1;
action[REST].proceedure=rest;
strcpy_s(action[REST].msg,100,"Resting...");

action[BATHE].bath_disease=1;
action[BATHE].proceedure=bathe;
strcpy_s(action[BATHE].msg,100,"Bathing...");

action[RESTHEAL].energy=1;
action[RESTHEAL].proceedure=restandheal;
strcpy_s(action[RESTHEAL].msg,100,"Resting and healing...");

action[MAKEFIRE].proceedure=makefire;
strcpy_s(action[MAKEFIRE].msg,100,"Making fire...");
action[MAKEFIRE].numskills=1;
action[MAKEFIRE].skill[0]=FIREMAKING;
action[MAKEFIRE].xp[0]=50;
action[MAKEFIRE].numparts=2;
action[MAKEFIRE].part[0]=WOOD;
action[MAKEFIRE].part[1]=TINDER;
action[MAKEFIRE].partqty[0]=2;
action[MAKEFIRE].partqty[1]=1;
action[MAKEFIRE].numtools=1;
action[MAKEFIRE].tool[0]=FIRESTICKS;
action[MAKEFIRE].toolqty[0]=1;

action[EAT].proceedure=eatfood;
strcpy_s(action[EAT].msg,100,"Eating food...");

action[LEARN].proceedure=research_skill;

action[COOK].proceedure=cook_food;
strcpy_s(action[COOK].msg,100,"Cooking food...");

action[FIND].proceedure=find_object;
strcpy_s(action[FIND].msg,100,"Searching for object...");

action[PLAYWITHFIRE].proceedure=play_with_fire;
strcpy_s(action[PLAYWITHFIRE].msg,100,"Playing with fire...");

action[MAKESHELTER].proceedure=make_shelter;
strcpy_s(action[MAKESHELTER].msg,100,"Making shelter...");

action[DEMOLISHSHELTER].proceedure=demolish_shelter;
strcpy_s(action[DEMOLISHSHELTER].msg,100,"Demolishing shelter...");

action[ENTERSHELTER].proceedure=entershelter;
strcpy_s(action[ENTERSHELTER].msg,100,"Entering shelter...");

action[MOVE].proceedure=move;
strcpy_s(action[MOVE].msg,100,"Traveling to new location...");

action[INSPECTSHELTER].proceedure=inspect_shelter;
strcpy_s(action[INSPECTSHELTER].msg,100,"Inspecting shelter...");

action[REPAIRSHELTER].proceedure=repair_shelter;
strcpy_s(action[REPAIRSHELTER].msg,100,"Repairing shelter...");

action[BUTCHER].proceedure=butcher_animal;
strcpy_s(action[BUTCHER].msg,100,"Butchering animal...");

action[DEBONE].proceedure=getbone_animal;
strcpy_s(action[DEBONE].msg,100,"Getting bone from animal...");

action[GETTRINKETS].proceedure=gettrinkets_animal;
strcpy_s(action[GETTRINKETS].msg,100,"Getting trinkets from animal...");

action[SACRIFICE].proceedure=sacrifice_animal;
strcpy_s(action[SACRIFICE].msg,100,"Sacrificing animal...");

action[SKIN].proceedure=skin_animal;
strcpy_s(action[SKIN].msg,100,"Skinning animal...");

action[LEAVESHELTER].proceedure=leaveshelter;
strcpy_s(action[LEAVESHELTER].msg,100,"Leaving shelter...");

action[BATHEWATERSKIN].proceedure=bathewaterskin;
strcpy_s(action[BATHEWATERSKIN].msg,100,"Bathing from waterskins...");
action[BATHEWATERSKIN].numparts=1;
action[BATHEWATERSKIN].part[0]=WATER;
action[BATHEWATERSKIN].partqty[0]=1;
action[BATHEWATERSKIN].numtools=1;
action[BATHEWATERSKIN].tool[0]=WATERSKIN;
action[BATHEWATERSKIN].toolqty[0]=1;

action[FORRAGE].proceedure=forrage;
strcpy_s(action[FORRAGE].msg,100,"Forraging for food...");

action[FILLWATERSKINRAIN].proceedure=fill_waterskins_rain;
strcpy_s(action[FILLWATERSKINRAIN].msg,100,"Filling waterskins with rainwater...");

action[TRAIN].proceedure=train;

strcpy_s(action[STARGAZE].msg,100,"Stargazing...");
action[STARGAZE].proceedure=stargaze;

action[FILLWATERSKIN].proceedure=fill_waterskins;
strcpy_s(action[FILLWATERSKIN].msg,100,"Filling waterskins...");

action[SWIM].proceedure=swim;
strcpy_s(action[SWIM].msg,100,"Swimming...");

action[MAKEBEDDING].proceedure=make_bedding;
strcpy_s(action[MAKEBEDDING].msg,100,"Making bedding...");

action[CLIMBTREE].proceedure=climbtree;
strcpy_s(action[CLIMBTREE].msg,100,"Climbing tree...");

action[CLIMBDOWN].proceedure=climbdownfromtree;
strcpy_s(action[CLIMBDOWN].msg,100,"Climbing down from tree...");

action[MAKEBEDSHELTER].proceedure=makebedshelter;
strcpy_s(action[MAKEBEDSHELTER].msg,100,"Making bedding in shelter...");

strcpy_s(action[CHECKBEDDING].msg,100,"Checking bedding condition...");
action[CHECKBEDDING].proceedure=checkbedding;

strcpy_s(action[FIXBEDDING].msg,100,"Repairing bedding...");
action[FIXBEDDING].proceedure=fixbedding;

strcpy_s(action[DANCE].msg,100,"Dancing...");
action[DANCE].proceedure=dance;

strcpy_s(action[PLAYDRUM].msg,100,"Playing drums...");
action[PLAYDRUM].proceedure=playdrum;

strcpy_s(action[PLAYFLUTE].msg,100,"Playing flute...");
action[PLAYFLUTE].proceedure=playflute;

strcpy_s(action[SING_ACTION].msg,100,"Singing...");
action[SING_ACTION].proceedure=sing;

strcpy_s(action[TELLJOKE].msg,100,"Telling joke...");
action[TELLJOKE].proceedure=telljoke;

strcpy_s(action[TELLSTORY].msg,100,"Telling story...");
action[TELLSTORY].proceedure=tellstory;

action[FISH].proceedure=fish;

strcpy_s(action[CAPTUREANIMAL].msg,100,"Capturing animal...");
action[CAPTUREANIMAL].proceedure=capture_animal;

strcpy_s(action[FREEANIMAL].msg,100,"Freeing animal...");
action[FREEANIMAL].proceedure=free_animal;

strcpy_s(action[TAMEANIMAL].msg,100,"Taming animal...");
action[TAMEANIMAL].proceedure=tame_animal;

strcpy_s(action[WATCHCLOUDS].msg,100,"Watching clouds...");
action[WATCHCLOUDS].proceedure=watchclouds;

strcpy_s(action[FIXOBJECT].msg,100,"Fixing object...");
action[FIXOBJECT].proceedure=fix_object;

strcpy_s(action[GETTENDON].msg,100,"Getting tendon from animal...");
action[GETTENDON].proceedure=get_tendon_animal;
action[GETTENDON].numtools=1;
action[GETTENDON].tool[0]=STONEKNIFE;
action[GETTENDON].toolqty[0]=1;

strcpy_s(action[MAKESTOREPIT].msg,100,"Building storage pit...");
action[MAKESTOREPIT].proceedure=make_storepit;

strcpy_s(action[INSPECTSTOREPIT].msg,100,"Inspecting storage pit...");
action[INSPECTSTOREPIT].proceedure=inspect_storepit;

strcpy_s(action[REPAIRSTOREPIT].msg,100,"Repairing storage pit...");
action[REPAIRSTOREPIT].proceedure=repair_storepit;

strcpy_s(action[EXAMINEMONOLITH].msg,100,"Examinimg monolith...");
//action[EXAMINEMONOLITH].proceedure=examine_monolith;

strcpy_s(action[ENTERCAVE].msg,100,"Entering cave...");
action[ENTERCAVE].proceedure=entercave;

strcpy_s(action[LEAVECAVE].msg,100,"Leaving cave...");
action[LEAVECAVE].proceedure=leavecave;

strcpy_s(action[SEARCHBODY].msg,100,"Searching body...");
action[SEARCHBODY].proceedure=searchbody;

strcpy_s(action[LEARNFROMCAVEMAN].msg,100,"Learning from caveman...");
action[LEARNFROMCAVEMAN].proceedure=learn_from_caveman;

strcpy_s(action[TEACHCAVEMAN].msg,100,"Teaching caveman...");
action[TEACHCAVEMAN].proceedure=teach_caveman;

strcpy_s(action[LISTEN2STORY].msg,100,"Listening to story...");
action[LISTEN2STORY].proceedure=listen2story;

strcpy_s(action[TEACHBANDMEMBER].msg,100,"Teaching bandmember...");
action[TEACHBANDMEMBER].proceedure=teach_bandmember;

strcpy_s(action[TELLJOKECLAN].msg,100,"Telling joke to bandmember...");
action[TELLJOKECLAN].proceedure=telljokeclan;

strcpy_s(action[TELLSTORYCLAN].msg,100,"Telling story to bandmember...");
action[TELLSTORYCLAN].proceedure=tellstoryclan;

strcpy_s(action[LISTEN2JOKE].msg,100,"Listening to joke...");
action[LISTEN2JOKE].proceedure=listen2joke;

strcpy_s(action[ENTERCAVERN].msg,100,"Entering cavern...");
action[ENTERCAVERN].proceedure=entercavern;

strcpy_s(action[LEAVECAVERN].msg,100,"Leaving cavern...");
action[LEAVECAVERN].proceedure=leavecavern;

strcpy_s(action[BUILDPERMSHEL].msg,100,"Building permenant shelter...");
action[BUILDPERMSHEL].proceedure=buildpermshel;

strcpy_s(action[INSPECTPERMSHEL].msg,100,"Inspecting permenant shelter...");
action[INSPECTPERMSHEL].proceedure=inspectpermshel;

strcpy_s(action[REPAIRPERMSHEL].msg,100,"Repairing permenant shelter...");
action[REPAIRPERMSHEL].proceedure=repairpermshel;

strcpy_s(action[DEMOLISHPERMSHEL].msg,100,"Demolishing permenant shelter...");
action[DEMOLISHPERMSHEL].proceedure=demolishpermshel;

strcpy_s(action[CLEARRUBBLE].msg,100,"Clearing rubble...");
action[CLEARRUBBLE].proceedure=NULL;

strcpy_s(action[MAKERAFT].msg,100,"Making raft...");
action[MAKERAFT].proceedure=make_raft;

strcpy_s(action[LEARNSAILING].msg,100,"Learning sailing...");
action[LEARNSAILING].proceedure=learn_sailing;

strcpy_s(action[BOARDRAFT].msg,100,"Boarding raft...");
action[BOARDRAFT].proceedure=board_raft;

strcpy_s(action[INSPECTRAFT].msg,100,"Checking raft...");
action[INSPECTRAFT].proceedure=check_raft;

strcpy_s(action[REPAIRRAFT].msg,100,"Repairing raft...");
action[REPAIRRAFT].proceedure=repair_raft;

strcpy_s(action[MOVERAFT].msg,100,"Moving on raft...");
action[MOVERAFT].proceedure=move_raft;

strcpy_s(action[DISEMBARK].msg,100,"Disembarking...");
action[DISEMBARK].proceedure=disembark;

strcpy_s(action[PRAY].msg,100,"Making sacrifice...");
action[PRAY].proceedure=pray;

action[PRAYFIRE].proceedure=prayfire;
strcpy_s(action[PRAYFIRE].msg,100,"Making sacrificial fire...");
action[PRAYFIRE].numskills=1;
action[PRAYFIRE].skill[0]=FIREMAKING;
action[PRAYFIRE].xp[0]=50;
action[PRAYFIRE].numparts=2;
action[PRAYFIRE].part[0]=WOOD;
action[PRAYFIRE].part[1]=TINDER;
action[PRAYFIRE].partqty[0]=2;
action[PRAYFIRE].partqty[1]=1;
action[PRAYFIRE].numtools=1;
action[PRAYFIRE].tool[0]=FIRESTICKS;
action[PRAYFIRE].toolqty[0]=1;

action[POISONWPN].proceedure=poison_wpn;
strcpy_s(action[POISONWPN].msg,100,"Poisoning weapon...");

action[APPLYCAMO].proceedure=apply_camo;
strcpy_s(action[APPLYCAMO].msg,100,"Applying camoflage...");
action[APPLYCAMO].r.numskills=1;
action[APPLYCAMO].r.skill[0]=CAMOFLAGE;
action[APPLYCAMO].r.xp[0]=50;
action[APPLYCAMO].r.numparts=1;
action[APPLYCAMO].r.part[0]=CORDAGE;
action[APPLYCAMO].r.partqty[0]=1;
action[APPLYCAMO].r.numtools=1;
action[APPLYCAMO].r.tool[0]=STONEKNIFE;
action[APPLYCAMO].r.toolqty[0]=1;

action[USELODESTONE].proceedure=use_lodestone;
strcpy_s(action[USELODESTONE].msg,100,"Using lodestone...");
action[USELODESTONE].r.numskills=1;
action[USELODESTONE].r.xp[0]=500;
action[USELODESTONE].r.numparts=1;
action[USELODESTONE].r.part[0]=WATER;
action[USELODESTONE].r.partqty[0]=10;
action[USELODESTONE].r.numtools=3;
action[USELODESTONE].r.tool[0]=LODESTONE;
action[USELODESTONE].r.tool[1]=CLAYPOT;
action[USELODESTONE].r.tool[2]=WOOD;
action[USELODESTONE].r.toolqty[0]=1;
action[USELODESTONE].r.toolqty[1]=1;
action[USELODESTONE].r.toolqty[2]=1;
action[USELODESTONE].r.time=4500;
action[USELODESTONE].r.chance=7500;
action[USELODESTONE].r.numbonusskills=1;
action[USELODESTONE].r.numboostedskills=1;

action[PUTOUTFIRE].proceedure=putoutfire;
strcpy_s(action[PUTOUTFIRE].msg,100,"Putting out fire...");

action[KILLCAPTURED].proceedure=kill_captured;
strcpy_s(action[KILLCAPTURED].msg,100,"Killing animal...");

strcpy_s(action[MAKEOBJ2].msg,100,"Making object...");
action[MAKEOBJ2].proceedure=make_object2;

strcpy_s(action[CHECKTRAP].msg,100,"Checking trap...");
action[CHECKTRAP].proceedure=check_trap;
action[CHECKTRAP].r.chance=10000;
action[CHECKTRAP].r.time=50;

strcpy_s(action[CHECKWEATHER].msg,100,"Checking weather...");
action[CHECKWEATHER].proceedure=check_weather;
action[CHECKWEATHER].r.chance=10000;
action[CHECKWEATHER].r.time=50;

strcpy_s(action[CHECKFIRE].msg,100,"Checking fire...");
action[CHECKFIRE].proceedure=check_fire;
action[CHECKFIRE].r.chance=10000;
action[CHECKFIRE].r.time=50;

strcpy_s(action[DEMOLISH_LANDMARK].msg,100,"Demolishing landmark...");
action[DEMOLISH_LANDMARK].proceedure=demolish_landmark;
action[DEMOLISH_LANDMARK].r.chance=10000;
action[DEMOLISH_LANDMARK].r.time=13500;

strcpy_s(action[DEMOLISH_BEDDING].msg,100,"Demolishing bedding...");
action[DEMOLISH_BEDDING].proceedure=demolish_bedding;
action[DEMOLISH_BEDDING].r.chance=10000;
action[DEMOLISH_BEDDING].r.time=4500;

strcpy_s(action[INSPECT_TRAP].msg,100,"Inspecting trap...");
action[INSPECT_TRAP].proceedure=inspect_trap;
action[INSPECT_TRAP].r.chance=10000;
action[INSPECT_TRAP].r.time=4500;

strcpy_s(action[REPAIR_WORLDOBJ].msg,100,"Repairing object...");
action[REPAIR_WORLDOBJ].proceedure=repair_world_object;
action[REPAIR_WORLDOBJ].r.chance=10000;
action[REPAIR_WORLDOBJ].r.time=4500;

strcpy_s(action[DEMOLISH_TRAP].msg,100,"Demolishing trap...");
action[DEMOLISH_TRAP].proceedure=demolish_trap;
action[DEMOLISH_TRAP].r.chance=10000;
action[DEMOLISH_TRAP].r.time=4500;

strcpy_s(action[INSPECT_LANDMARK].msg,100,"Inspecting landmark...");
action[INSPECT_LANDMARK].proceedure=inspect_landmark;
action[INSPECT_LANDMARK].r.chance=10000;
action[INSPECT_LANDMARK].r.time=4500;

strcpy_s(action[REPAIR_TRAP].msg,100,"Repairing trap...");
action[REPAIR_TRAP].proceedure=repair_trap;
action[REPAIR_TRAP].r.chance=10000;
action[REPAIR_TRAP].r.time=4500;

strcpy_s(action[DAYDREAM].msg,100,"Daydreaming...");
action[DAYDREAM].proceedure=daydream;

strcpy_s(action[TALK2FRIENDLY].msg,100,"Talking to friendly caveman...");
action[TALK2FRIENDLY].proceedure=talk2friendly;

strcpy_s(action[TALK2BANDMEMBER].msg,100,"Talking to band member...");
action[TALK2BANDMEMBER].proceedure=talk2bandmember;

strcpy_s(action[LISTEN2BANDMEMBER].msg,100,"Listening to band member...");
action[LISTEN2BANDMEMBER].proceedure=listen2bandmember;

}



Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php

### #14Norman Barrows  Members

6291
Like
0Likes
Like

Posted 27 May 2014 - 01:17 PM

Finally, call the function variable. This is the slick part. Instead of a huge switch on action_type, you just do:

void doactionmodeB(int cm1)
{
int a;
a=7+cm[cm1].mood/13;
if (frame<=a) action[cm[cm1].current_action].proceedure();
}


Note that working with DLLs, you may need to pay particular attention to calling conventions ( IE cdecel vs fastcall etc.).

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php

### #15Bacterius  Members

13100
Like
1Likes
Like

Posted 27 May 2014 - 07:02 PM

Any reason you initialize a fixed size array with ZeroMemory? Usually you just do "array = {0};", it's cleaner, portable, and doesn't invoke a function that is possibly not even built-in on some compilers (I take it maxactions is known at compile-time). If the indices into the array are also known at compile time, the compiler may even decide zeroing the array is unnecessary and skip it altogether after doing some static analysis (though I doubt that, admittedly, but just saying that would probably never be possible with a call to ZeroMemory bang in the middle of the function).

“If I understand the standard right it is legal and safe to do this but the resulting value could be anything.”

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.