ATTENTION

This FlexSim Community Forum is read-only. Please post any new questions, ideas, or discussions to our new community (we call it Answers) at https://answers.flexsim.com/. Our new Question & Answer site brings a modern, mobile-friendly interface and more focus on getting answers quickly. There are a few differences between how our new Q&A community works vs. a classic, threaded-conversation-style forum like the one below, so be sure to read our Answers Best Practices.


flexsim.com

Go Back   FlexSim Community Forum > FlexSim Software > Q&A
Downloads

Q&A Using Flexsim and building models

  #1  
Old 04-28-2008
Tom David's Avatar
Tom David Tom David is offline
Flexsim User
 
Join Date: Aug 2007
Location: Schwaebisch Gmuend, Germany
Posts: 430
Downloads: 157
Uploads: 47
Thanks: 486
Thanked 450 Times in 233 Posts
Rep Power: 520
Tom David has a brilliant futureTom David has a brilliant futureTom David has a brilliant futureTom David has a brilliant futureTom David has a brilliant futureTom David has a brilliant futureTom David has a brilliant futureTom David has a brilliant futureTom David has a brilliant futureTom David has a brilliant futureTom David has a brilliant future
Default DLL Linking - ProcessorProcessTime

Task:
The process time for a processor should be defined in an external C++ Function “ProcessorProcessTime”, where 0 < ProcessTime < MaxProcessTime. Also the name of the processor (instance, object) and the name of the involved item should be returned.

The DLL-Linking Template is the following if you switch the node to DLL:

/**DLL path: *//**/"../libraries/thedll.dll"/**/
/** \nFunction name:*//**/"dllfunction"/**/

1. How to call the DLL-Function with the parameters “current”, “item” and “MaxProcessTime?


An alternative way could be to call the DLL-Function with nodefunction() and a label and hand over the parameters.

//Parameter „Process Time” als Flexscript
treenode current = ownerobject(c);
treenode item = parnode(1);
/**DLL Function Call*/
// CALL FUNCTION FROM DLL OVER LABEL DLL_ProcessorProcessTime
double MaxProcessTime = 77.0;
double returnval = nodefunction(label(current, "DLL_ProcessorProcessTime"),
tonum(item), MaxProcessTime);
return returnval;

//Label „DLL_ProcessorProcessTime”
dll: "../libraries/thedll.dll"
function: "ProcessorProcessTime"

This is working and this is how I have solved this problem for myself.


2. Which references (Parameters) are between the nodefunction-interface and the FLEXSIMINTERFACE?

In the flexsimdefs.h you can find for the FLEXSIMINTERFACE:
code == 0
c != NULL
theclass == c
input == NULL
output == NULL
involved == NULL
callpoint != NULL

3. For what can these parameters be used? How to use them?

The code in the dll should be something like:

visible double ProcessorProcessTime(FLEXSIMINTERFACE)
{
// FLEXSIMINTERFACE is defined by
// #define FLEXSIMINTERFACE int code, linkedlist * c,
// linkedlist * theclass, void * input, void * output,
// linkedlist * iinvolved, _callpoint * callpoint
// ACTUAL ARGUMENTS OF ProcessorProcessTime
int icode = code;
int iinst = (int)tonum(c);
int iclass = (int)tonum(theclass);
int iinput = (int)tonum((linkedlist*)input);
int ioutput = (int)tonum((linkedlist*)output);
int iinvolved = (int)tonum((linkedlist*)involved);
int icallpoint = (int)tonum((linkedlist*)callpoint);
// POINTER TO OBJECT
treenode current = ownerobject(c);
// POINTER TO ITEM via callpoint
treenode item = parnode(1);
// PARAMETER VALUE via callpoint
int iMax = (int)parval(2);
// RANDOM PROCESSING TIME
int irand = 9999;
while ( irand > iMax )
{
irand = rand();
}
dProcessTime = (double)irand;
// DEFINE A MESSAGE ARRAY FROM TYPE CHAR
char message[1000];
// ASSIGN MESSAGE
sprintf(message, "ProcessorProcessTime: \nObject:%s \n
Item: %s \nProcessTime: %f",
getname(current).c_str(),
getname(item).c_str(),
dProcessTime);
// STOP SIMULATION RUN
stop(1);
// REPAINT ALL WINDOWS
repaintall();
// SCREEN MESSAGE WHERE USER CAN DECIDE TO GO OR TO STOP
// SIMULATION RUN
if(msg("DLL ProcessorProcessTime", message,0) == 1) {go(1);}
else {stop(1);}
// RPINT INFORMATION INTO OUTPUT CONSOLE
pt("Time: "); pf(time()); pr();
pt(message); pr(); pr();
pd(icode); pr(); pd(iinst); pr(); pd(iclass); pr();
pd(iinput); pr(); pd(ioutput); pr(); pd(iinvolved); pr();
pd(icallpoint); pr(); pr();
return dProcessTime;
}

4. Can this code work and what is to do to make it work?

I am not a programmer and not sure if this goes in the right direction. I got these questions from a user and maybe some of you can give me some hints and help.

Thanks in advance.
tom the (A)tom
__________________
tom the (A)tom: "We have solved our problems ... now we have to fight the solutions."
  #2  
Old 04-28-2008
Lars-Olof Leven Lars-Olof Leven is offline
Flexsim Distributor
 
Join Date: Aug 2007
Location: Sweden, Borlnge
Posts: 312
Downloads: 278
Uploads: 2
Thanks: 300
Thanked 256 Times in 139 Posts
Rep Power: 330
Lars-Olof Leven is a splendid one to beholdLars-Olof Leven is a splendid one to beholdLars-Olof Leven is a splendid one to beholdLars-Olof Leven is a splendid one to beholdLars-Olof Leven is a splendid one to beholdLars-Olof Leven is a splendid one to beholdLars-Olof Leven is a splendid one to behold
Default

Hi Tom,

I would use User Command to call the DLL_ProcessorProcessTime.
In User Command you define a command called ProcessTime and in that you write the call to the DLL
dll: "../libraries/thedll.dll"

function: "ProcessorProcessTime"

To call the ProcessTime you call it with: ProcessTime(tonum(current),tonum(item),MaxProcessT ime);

In your C-code
visible double ProcessorProcessTime(FLEXSIMINTERFACE)
{
// FLEXSIMINTERFACE is defined by
// #define FLEXSIMINTERFACE int code, linkedlist * c,
// linkedlist * theclass, void * input, void * output,
// linkedlist * iinvolved, _callpoint * callpoint
// ACTUAL ARGUMENTS OF ProcessorProcessTime

// POINTER TO OBJECT

fsnode* current = parnode(1);
// POINTER TO ITEM via callpoint
fsnode* item = parnode(2);
// PARAMETER VALUE via callpoint
int iMax = (int)parval(3);
// RANDOM PROCESSING TIME
int irand = 9999;
while ( irand > iMax )
{
irand = rand();
}
dProcessTime = (double)irand;
// DEFINE A MESSAGE ARRAY FROM TYPE CHAR
char message[1000];
// ASSIGN MESSAGE
sprintf(message, "ProcessorProcessTime: \nObject:%s \n
Item: %s \nProcessTime: %f",
getname(current).c_str(),
getname(item).c_str(),
dProcessTime);
// STOP SIMULATION RUN
stop(1);
// REPAINT ALL WINDOWS
repaintall();
// SCREEN MESSAGE WHERE USER CAN DECIDE TO GO OR TO STOP
// SIMULATION RUN
if(msg("DLL ProcessorProcessTime", message,0) == 1) {go(1);}
else {stop(1);}
// RPINT INFORMATION INTO OUTPUT CONSOLE
pt("Time: "); pf(time()); pr();
pt(message); pr(); pr();

return dProcessTime;
}

Point 3 and 4 I hope Flexsim or someone else can explain.

Lars-Olof
  #3  
Old 04-28-2008
Brandon Peterson's Avatar
Brandon Peterson Brandon Peterson is offline
The Flexsim Consultant
 
Join Date: Jul 2007
Location: Salt Lake City, Utah
Posts: 382
Downloads: 29
Uploads: 6
Thanks: 192
Thanked 516 Times in 235 Posts
Rep Power: 490
Brandon Peterson has a brilliant futureBrandon Peterson has a brilliant futureBrandon Peterson has a brilliant futureBrandon Peterson has a brilliant futureBrandon Peterson has a brilliant futureBrandon Peterson has a brilliant futureBrandon Peterson has a brilliant futureBrandon Peterson has a brilliant futureBrandon Peterson has a brilliant futureBrandon Peterson has a brilliant futureBrandon Peterson has a brilliant future
Default

Tom,

From what I know the same information that is passed to the function calling the DLL is passed into the DLL. So, Lars nailed it. If you want to pass different information into the DLL than is passed normally into a "process time" function or some other function then you would want to use a User Command or Node Funciton to call the DLL and pass that function the information you want to use.

Inside of the DLL you will want to use the parval and parnode commands to get to those variables.

So if the function looked like this:
myfunc(current, item, somedouble, centerobject(current, 1));

The DLL would look like this:
fsnode *current = parnode(1);
fsnode *item = parnode(2);
fsnode *mydouble = parval(3);
fsnode *cobj = parnode(4);

This is how I've done it in the past, AJ or Anthony might have something better.

Good Luck,
Brandon
__________________
thats not normal.
  #4  
Old 04-28-2008
Tom David's Avatar
Tom David Tom David is offline
Flexsim User
 
Join Date: Aug 2007
Location: Schwaebisch Gmuend, Germany
Posts: 430
Downloads: 157
Uploads: 47
Thanks: 486
Thanked 450 Times in 233 Posts
Rep Power: 520
Tom David has a brilliant futureTom David has a brilliant futureTom David has a brilliant futureTom David has a brilliant futureTom David has a brilliant futureTom David has a brilliant futureTom David has a brilliant futureTom David has a brilliant futureTom David has a brilliant futureTom David has a brilliant futureTom David has a brilliant future
Default

Lars-Olof,
Brandon,

I understand now that both of you will do it the same way I did it in my alternative way beside that you prefer to use a user command where I used a label. But it the same idea and same structure based on the fact that the parameters you use calling the user command or label are given further to the DLL. So in the DLL you can use these parameters.

The question is if this is the only solution or is there a way directly to hand over parameters to the DLL. I am fine with the above solution, but a user asks if there is another way.
If this is the only way than I agree with you to use a user command would be the easiest and readable solution.
But why has the standard template (if you switch code to DLL) than no option to hand over parameters? Because there is no way to hand over parameters directly?

Yes, I also hope that I get some more response (Point 3 and Point 4), because I like to understand the whole thing and I like to give the user a good and right reply. And he likes to understand this other stuff.

Anyway, thanks guys for these first replies.
tom the (A)tom
__________________
tom the (A)tom: "We have solved our problems ... now we have to fight the solutions."
  #5  
Old 04-29-2008
AJ Bobo's Avatar
AJ Bobo AJ Bobo is offline
Flexsim Senior Developer
 
Join Date: Jul 2007
Posts: 108
Downloads: 8
Uploads: 0
Thanks: 23
Thanked 89 Times in 41 Posts
Rep Power: 221
AJ Bobo is a jewel in the roughAJ Bobo is a jewel in the roughAJ Bobo is a jewel in the roughAJ Bobo is a jewel in the rough
Default

Tom,

I've used DLLs in the last two or three projects I've done and in most cases I've been using them with the User Command method mentioned by Brandon and Lars-Olof. That's worked very well for me.

As for those weird parameters (input, output, callpoint, etc) in the FLEXSIMINTERFACE, I've never worried about what they are for. I've never had to use them directly. I just get the parameters I need using the parval() and parnode() commands (like Brandon described). Those commands are created to retrieve data from the callpoint object as needed.

There is no way to pass values directly to the DLL functions from the node that's toggled as DLL. The reason is that the DLL system is designed to treat the node as a sort of pass-through conduit to the actual function to call. Whatever parameters are passed to the node in the nodefunction() call will be passed straight through to the DLL (when using a User Command nodefunction() is still called behind the scenes). Basically, I think the trick is to write DLL functions as if they are nodefunctions, but you have the added bonus of being able to use C++ functionality. If there are values that need to be used in a function every time it's called (and if those values never change) they can be hard-coded into the function itself. This is sometimes a dangerous practice, but you can do it if you need to.
  #6  
Old 04-29-2008
Anthony Johnson's Avatar
Anthony Johnson Anthony Johnson is offline
Manager of Product Development
 
Join Date: Jul 2007
Posts: 440
Downloads: 86
Uploads: 4
Thanks: 171
Thanked 899 Times in 288 Posts
Rep Power: 735
Anthony Johnson has a reputation beyond reputeAnthony Johnson has a reputation beyond reputeAnthony Johnson has a reputation beyond reputeAnthony Johnson has a reputation beyond reputeAnthony Johnson has a reputation beyond reputeAnthony Johnson has a reputation beyond reputeAnthony Johnson has a reputation beyond reputeAnthony Johnson has a reputation beyond reputeAnthony Johnson has a reputation beyond reputeAnthony Johnson has a reputation beyond reputeAnthony Johnson has a reputation beyond repute
Default

Tom,
On your point of using the callpoint, involved, etc., AJ is correct. Those parameters are only meant to be available so that you can use the standard access parameters that a nodefunction has: parval(), parnode(), c, i, etc. They are really meant to be "invisible" to you as the user, meaning you don't worry about them. You just call parval(), parnode(), etc.

To your other point of getting direct access to a function in the dll, the only time that you would need to do this is if you are implementing C++ code that accessed functions in the dll. If your code is implemented in flexscript, then you can use the user command method (and you don't have to use tonum() because flexscript isn't strongly typed). However, if you're accessing the dll function from C++, you get issues in calling the user command because you have to pass all numbers, and therefore you have to do the tonum() thing. So right now, my answer to that is, don't use C++. Just implement your model code in flexscript, and everything works just as if your code is connecting directly to a dll function that takes parameters so-and-so.

However, in some cases I realize that C++ is required, which presents the tonum() problem, where in order for it to work in C++, you have to add these extra tonum() things into your parameters of the call to the user command. For this problem I have found a solution that will directly connect Flexsim to non-FLEXSIMINTERFACE functions that you specify in the dll. I've got this working for the Rail API, but you have to change Flexsim4/program/config/flexsimexeB.txt to get the dll to be delay-loaded. We'll hopefully make this model-accessible in future releases. Right now I'm in the middle of an urgent project, so I don't have the time to document it all, but when I get the time, I'll put an article together.



All times are GMT -6.
Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2020, vBulletin Solutions Inc.
Copyright 1993-2018 FlexSim Software Products, Inc.