- Index
- » Usage and Applications
- » OpenModelica Usage and Applications
- » C++ call
C++ call
Re: C++ call
Yes, but you need to force the compiler to link it in C-mode (no function overloading):
myFile.cpp:
external "C" {
int myFunction(int x) {
return 3*x;
}
}
- sjoelund.se
- 1700 Posts
Re: C++ call
I was at the same point some month ago...
You will be in trouble, if your C++ function requires more C++ code or libraries which make C-mode linking impossible.
I decided to use fifos / sockets to interface my C++ stuff then.
So the simulation and the controller software (C++) are seperately build applications exchanging arrays through the socket.
Anyway, i have trouble using my old implementation with the latest version of OM (see my previous thread).
I can provide the code (as soon as it works) if you are interested...
Cheers,
Joerg
Re: C++ call
Yes, mixing C and C++ can be a bit weird, but it's mostly if you include C++ headers in a C file.
If you create a function fn in a C++ file that only calls the C++-function you want to call, and make it linked external "C", and only expose "external int fn(int);" in a header (or the automatically generated code of OMC), you are usually fine. It's always possible to create such an entry point if it doesn't use C++ datatypes.
- sjoelund.se
- 1700 Posts
Re: C++ call
Hi!
It seems to be not fast enough.
The cpp-function receives data in a fast way but the return to OM seems slow..
This is the code, it's just for test speed.
Code:
void crea_addr(struct sockaddr_in* addr,int port, char* server)
{
addr->sin_family = AF_INET;
addr->sin_addr.s_addr = inet_addr(server);
addr->sin_port = htons(port);
}
void importExt(int val, double* a,double* b,double* c)
{
WORD wVersionRequested = MAKEWORD(2,2);
WSADATA wsaData;
WSAStartup(wVersionRequested, &wsaData);
SOCKET sock;
SOCKADDR_IN addr;
char buf[100];
sock=socket(AF_INET, SOCK_STREAM, 0);
crea_addr(&addr,10503,"127.0.0.1");
if(connect(sock, (struct sockaddr*)&addr, sizeof(struct sockaddr))==0)
{
int n=recv(sock, buf, sizeof(buf), 0);
closesocket(sock);
buf[n]=0;
cout<< buf<<" \n";
*a=0;
*b=0;
*c=0;
closesocket(sock);
return ;
}
else
{
*a=0;
*b=0;
*c=0;
}
return;
}
As I said the cout is called fast, but results from OMI tu my application are slower..Obviously no problems if I close the socket in my application..
Any suggest?
Thanks,
Francesco
Re: C++ call
Do you connect() every time you exchange data? That seems... Slow. Maybe you could solve it by using a global variable for the connection or external objects instead.
- sjoelund.se
- 1700 Posts
Re: C++ call
Yes I connect everytime because I thougth I couldn't stay connected because the external function is called at every step of the simulation..Maybe I haven't well understood how it works exactly..
Another question..do you think I can declare parameters instead of variables in order to modify them using classical OMI commands? Is this way fast enough in receiving input?
I need to change these values almost every time step.
Re: C++ call
If you have a global variable (or a static local variable), you can store a global state that does not change between function calls.
static int is_initialized = 0;
if (!is_initialized) {
connect();
is_initialized = 1;
}
... code goes here; always connected. It's the same connection for all calls to the function though.
As for OMI, I have no clue
- sjoelund.se
- 1700 Posts
Re: C++ call
Well, you are doing closesocket(sock); And you'd need to make sock and the other data global to save it between calls.
- sjoelund.se
- 1700 Posts
Re: C++ call
Yes, I've done this..or I think I've done ..this is the new code
Code:
void importExt(int val, double* a,double* b,double* c)
{
static WORD wVersionRequested = MAKEWORD(2,2);
static WSADATA wsaData;
WSAStartup(wVersionRequested, &wsaData);
static SOCKET sock;
static SOCKADDR_IN addr;
static int is_initialized = 0;
if (!is_initialized)
{
sock=socket(AF_INET, SOCK_STREAM, 0);
crea_addr(&addr,10503,"127.0.0.1");
if(connect(sock, (struct sockaddr*)&addr, sizeof(struct sockaddr))==0);
is_initialized = 1;
}
if(is_initialized)
{
char buf[40]={0};
send(sock,"\0",sizeof("\0"),0);
int n;
n=recv(sock, buf, sizeof(buf), 0);
buf[n]=0;
cout<< buf<<" \n";
*a=0;
*b=0;
*c=0;
return ;
}
I can see some exchanges of data (both in OM and in my application) and then all stops waiting for something..but I don't have any result from simulator yet..
Re: C++ call
Fast enough for what? Maybe if you use a fixed size solver it will be faster.
Cheers,
Adrian Pop/
- adrpo
- 885 Posts
Re: C++ call
I'm just trying to change the numberOfintervals parameter of build() command but I don't understand how it works..
First of all: is this parameter the number of simulation step (and result sendings) in a second (during interactive simulation)?
I tried using 10, 100 and 1000 but the fastest is 100 (WHY? )
Re: C++ call
the number of intervals is the number of time steps the simulation will take.
For example, if you simulate from time 0 to 1.0 with 10 intervals, you will get output at 0.0, 0.1, 0.2, 0.3, ..., 1.0
If you have more intervals, the simulation will be slower
- sjoelund.se
- 1700 Posts
Re: C++ call
I was wrong again..the MSG_PEEK works because it doesn't clean the buffer and so the receive function always read the first input I send..I didn't notice it before..
I think the external function is called 10-11 times before sending the first results string..but I can't receive it..Maybe there's a problem in my application..
- Index
- » Usage and Applications
- » OpenModelica Usage and Applications
- » C++ call