• Which the release of FS2020 we see an explosition of activity on the forun and of course we are very happy to see this. But having all questions about FS2020 in one forum becomes a bit messy. So therefore we would like to ask you all to use the following guidelines when posting your questions:

    • Tag FS2020 specific questions with the MSFS2020 tag.
    • Questions about making 3D assets can be posted in the 3D asset design forum. Either post them in the subforum of the modelling tool you use or in the general forum if they are general.
    • Questions about aircraft design can be posted in the Aircraft design forum
    • Questions about airport design can be posted in the FS2020 airport design forum. Once airport development tools have been updated for FS2020 you can post tool speciifc questions in the subforums of those tools as well of course.
    • Questions about terrain design can be posted in the FS2020 terrain design forum.
    • Questions about SimConnect can be posted in the SimConnect forum.

    Any other question that is not specific to an aspect of development or tool can be posted in the General chat forum.

    By following these guidelines we make sure that the forums remain easy to read for everybody and also that the right people can find your post to answer it.

Reading and writing Lvar from C++

Messages
71
Country
norway
I looked into that , but I was not sure that SimConnect "commands" could be used within a DLL that is running in the P3Dv4 process. I was looking for some FSAPI "commands".

To me this looks like going out of the process and then back again. But, my knowledge of P3Dv4 DLL programming has just started to build up, so I have a try.
 

ddawson

Resource contributor
Messages
862
Country
canada
Go to my website and download
p3d_xml_vars_x64
It is a gauge that you can to the panel of a test aircraft. It will allow you to scroll through all lvars active in the session, giving you the ID, the name and the current value.
 
Messages
71
Country
norway
I have some trouble to get my head around the DLL programming in general and the lvar_interface dll

Lets say I just want to get the value of lvar "B767_AT_Arm_Sw"

Shouldn't that be done with the

GetLVarByName("B767_AT_Arm_Sw");


But, where in the dll code " dllmain.cpp" should it be?

Where does the actual code execution start?


here?

case DLL_PROCESS_ATTACH:
{
GetLVarByName("B767_AT_Arm_Sw");
}



I have only done C++ executable programming , not any DLL coding
 

ddawson

Resource contributor
Messages
862
Country
canada
You need to create a routine to handle the communications with your external app.
That routine is best initiated from within DLLStart().
The functions listed in lvar_interface.cpp will be called, as required from within your communications routine.
 
Messages
71
Country
norway
Go to my website and download
p3d_xml_vars_x64
It is a gauge that you can to the panel of a test aircraft. It will allow you to scroll through all lvars active in the session, giving you the ID, the name and the current value.


Tried it , but I didn't get it to work. The window comes up, but it is just a dark window. Probably my bad.

Where do the dll go? In the P3Dv4/Gauges folder or P3Dv4 main folder or somewhere else?

Or should it be started from the dll.xml file?

I have tried most alternatives listed above, but with no luck.



UPDATE:

Got it working after renaming the dll to xml_vars.gau


Working now fine, thanks.
 
Last edited:
Messages
71
Country
norway
I really liked the p3d_xlm_vars_64.dll I downloaded . it help me during the debug phase of my program.

It it possible for you to add some new features to it?

Like,
Increase outpu lines from 20 to lets say 100
Filterering of displayed lvar name
Copy function of all lines to clipboard for pasting to editor(NotePad)


If you do not have time, is the source available to modify?
 
Messages
2,077
Country
us-ohio
Why would you need 100 lines? You can simply click through the variables with your mouse... page after page.
 
Messages
71
Country
norway
I know I can scroll with mouse, but more visible lines(lvars) would be better(at leaset for my purpose).

The nicest would be a fixed font size and an increased/decreased number of lines when increasing/decreasing the window with mouse.

A filtering function is the most important though.
 
Messages
71
Country
norway
You need to create a routine to handle the communications with your external app.
That routine is best initiated from within DLLStart().
The functions listed in lvar_interface.cpp will be called, as required from within your communications routine.

I have added the code for initiating a communication client and it sets up a connection to the communication server( my C++ app)

After the initialization of the comm.client, P3D takes over.

I guess I need to create separate threads for reading/setting lvar values and reading/sending on the comm link.

These threads should not be started before the actual airplane I want to read/set lvar from.

This is my challenge and anyone who can share some hints of how to do this are welcomed.

I have tried to create these threads, but without success.


Is it possible to create threads in the DLLStart function?
 
Messages
71
Country
norway
Got the comm thread working now by using the


hcommThread = CreateThread(NULL, 1024, my_comm, NULL, 0, &ThreadID)

The _beginthread in your link I didn't know about. Is there a preferred one when programming in the P3D environment or are they more or less the same?
 
Messages
2,077
Country
us-ohio
_beginthread and _beginthreadex are the preferred functions to create threads these days. CreateThread is before security.
 
Messages
71
Country
norway
I have more or less finished my DLL project and are doing some testing to improve the performance.


I have a threadin my DLL that reads an airplane LVar values implemented as shown second code part below. It is , I believe, not a professional way of doing it , but it works.

Is there a better way to code this function, i.e. with a Callback function as found in SimConnect? See code below.

Code:
int hr = SimConnect_CallDispatch(hndl, MyDispatchProc, NULL);

void CALLBACK MyDispatchProc(SIMCONNECT_RECV* pData, DWORD cbData, void *pContext)
{

    switch (pData->dwID)
    {
    case SIMCONNECT_RECV_ID_SIMOBJECT_DATA:       // Receive and process the FSX DATA block
    {
        SIMCONNECT_RECV_SIMOBJECT_DATA *pObjData = (SIMCONNECT_RECV_SIMOBJECT_DATA*)pData;
        switch (pObjData->dwRequestID)
        {
        case SIM_REQ:
        {

            Sim_Data *pS = (Sim_Data*)&pObjData->dwData;

            SIM_SPD = pS->speed;

I.e. having the Callback result ( that only report changes) sent to switch, so not every LVars have to read all the time as in my code now.

Is there any examples available how to do this in the most efficient way? How do you write the Callback and how

Code:
while (airplane_running)
    {

MCP_AP_master_CAPTAIN = (int)GetLVarByID(1);

MCP_AP_master_FO = (int)GetLVarByID(2);
MCP_AT_mode = (int)GetLVarByID(3);
// and so on for all Lvars too be read

// .....

    if (MCP_AP_master_CAPTAIN == 1)
    {sendVarData(1414, 1);
    }else { sendVarData(1414, 0); }
    if (MCP_AP_master_FO == 1)
    {sendVarData(1415, 1);
    }else { sendVarData(1415, 0); }
    
    // on so on
 

JB3DG

Resource contributor
Messages
1,325
Country
southafrica
I make a single data definition using some obscure variable like IS USER SIM, and then I make a request data on simobject call that has the parameters set for it to return data every sim frame. Then I run my functions in the case where that request ID is hit.
 
Messages
71
Country
norway
I follow you on the last parts of your answer, but the
"I make a single data definition using some obscure variable like IS USER SIM",

I really do not understand. Could you try to explain this more in detail not only for me, but for others that are heading into DLL coding.
 

ddawson

Resource contributor
Messages
862
Country
canada
Jon is suggesting one way to get a callback on every sim frame - use RequestDataOnSimObject with a callback frequency of SIMCONNECT_PERIOD_SIM_FRAME.
Alternatively, you could call SubscribeToSystemEvent to request notification on each sim frame.
In actual fact, for external communications, such as you are considering, I think you might find that updating on each frame is a bit too much. I would start with the 6Hz or even 1sec notifications.

Also, it looks like you are hard coding the LVar ID's into your code. You can't do that, as you cannot rely on a given LVar having the same ID number in each session. You will need to check the ID number of each LVar before you access it. The ID numbers will be consistent over the life of the loaded aircraft, so you don't have to call check_named_variable in front of each call to get_named_variable_value.

Unfortunately, there is no way of knowing whether a particular LVar has changed values other than by reading it and comparing its current value to its previous value. This does mean that you will have to go through the entire list of LVars you are interested in each time you want to provide updated values - hence my suggestion to start with 6Hz rather than on each sim frame.
 
Messages
71
Country
norway
Jon is suggesting one way to get a callback on every sim frame - use RequestDataOnSimObject with a callback frequency of SIMCONNECT_PERIOD_SIM_FRAME.
Alternatively, you could call SubscribeToSystemEvent to request notification on each sim frame.
In actual fact, for external communications, such as you are considering, I think you might find that updating on each frame is a bit too much. I would start with the 6Hz or even 1sec notifications.

This is what I do for the Simconnect Variables I have, as some of the airplane's variables are done as Simconnect Variables.

Also, it looks like you are hard coding the LVar ID's into your code. You can't do that, as you cannot rely on a given LVar having the same ID number in each session. You will need to check the ID number of each LVar before you access it. The ID numbers will be consistent over the life of the loaded aircraft, so you don't have to call check_named_variable in front of each call to get_named_variable_value.

This was new for me. I thought the ID was hardcoded and therefore the same for all sessions. Thanks for letting me know this important fact. Then I will go over to use Lvars names instead of IDs.

Unfortunately, there is no way of knowing whether a particular LVar has changed values other than by reading it and comparing its current value to its previous value. This does mean that you will have to go through the entire list of LVars you are interested in each time you want to provide updated values - hence my suggestion to start with 6Hz rather than on each sim frame.

Ok, so I keep my LVars reading code, just change from using ID to Name when addressing Lvars.

Not sure I know how to do
hence my suggestion to start with 6Hz rather than on each sim frame.
when reading LVars other than adding a Sleep(200) in the while(airplane_running) loop.


Again, thanks a lot for the feedback.
 
Messages
71
Country
norway
I have my DLL working fine, but I want it to be active only when a specific airplane is loaded.

If another airplane is selected/loaded, the DLL should be deactivated.

I haven't found a good way of doing this yet. I know I could look for loaded airplane via SimConnect, and if not loaded, deactive all the DLL's active threads and if loaded again, active the threads.



I tried to rename it to a gau file and copied it the the Gauges folder and set it up in the panel.cfg of the airplane, but P3D crashes.

My understanding of gau vs dll, is that they are the same. Doing it this way should also have it active when the specific airplane is active.


Any ideas how to do this?
 
Last edited:

ddawson

Resource contributor
Messages
862
Country
canada
The way you have things set up, there really isn't a good way to keep the module inactive when not in use.
It doesn't matter how you want to identify a relevant aircraft, you are going to have to deal with the fact that users can rename things (aircraft folders, .air files, title strings.) How are you going to deal with aftermarket repaints?
You could put a gauge on the panel of the relevant aircraft. Its presence would tell the module to activate. Then you have to offer support to people who can't or won't modify panel.cfg files.

I'm going to reiterate my suggestion that you make the module the server and your external app the client.
That way, the module will only be active when it is responding to input from the app. In the context of cpu cycles, this amounts to virtually never, which is precisely what you want for an in-process add-on.
 
Top