Plugin-DLLs - LOTUS interfaces, supported features?

  • Hi all!


    I've come across the lexicon articles about the plugin DLLs and some questions occured in me, because I'd like to write/build a DLL for myself for a real speedometer (Hasler & Bern RT9 but that doesn't matter at this point), using an Arduino.


    What interface can we use to access the data in LOTUS? I mean what functions/methods with what variables? Is there a list somewhere, or the example code contains all the usable functions (ReceiveVarFloat...etc)? What features does the DLL plugin method support? Can it handle accessing to serial ports or intermediate objects like a port on the local IP address to use the data in another program? Can the DLLs use config files or is there any way to change a variable without building the whole DLL again (for example serial port numbers, if it can handle it)?



    As far as I understand, the ReceiveVarXYZ functions are called when a propriate typed variable changes in the game (in the example code the v_axle_mps_0_0 is sent through var.0), so the inner parts of those are like the Simstep functions of the script system. So if I need a variable like that, I need to code in inside one of these functions (of course with the corresponding type). Am I right so far?

    Also, it's been a very long time ago since I built any DLL files, so I have to ask, is there any easy way to build from such a code as the example (so written in Object Pascal)? Also what do I need to make the plugin work? Make a plugins folder in LOTUS main directory, make an .ini file with whatever name I want, make a DLL file, all in this folder and that's it?

  • Hi! :-)

    What interface can we use to access the data in LOTUS? I mean what functions/methods with what variables? Is there a list somewhere, or the example code contains all the usable functions (ReceiveVarFloat...etc)?

    I do not really understand what you mean with interface or methods in this context... https://www.lotus-simulator.de…php?entry/237-plugin-dll/ should describe everything...?

    What features does the DLL plugin method support? Can it handle accessing to serial ports or intermediate objects like a port on the local IP address to use the data in another program?

    If you write a DLL, you may use everything, which you get by Windows! ;-)

    Can the DLLs use config files or is there any way to change a variable without building the whole DLL again (for example serial port numbers, if it can handle it)?

    A DLL can also do read/write procedures... a DLL is nearly the same like an EXE... ;-)

    functions are called when a propriate typed variable changes in the game

    Currently, they are called just in every frame/loop.

    So if I need a variable like that, I need to code in inside one of these functions (of course with the corresponding type). Am I right so far?

    I do not really understand, what you mean... :-(

    Also, it's been a very long time ago since I built any DLL files, so I have to ask, is there any easy way to build from such a code as the example (so written in Object Pascal)? Also what do I need to make the plugin work? Make a plugins folder in LOTUS main directory, make an .ini file with whatever name I want, make a DLL file, all in this folder and that's it?

    Hmm, every information and also an example should be given by our two articles...


    https://www.lotus-simulator.de…php?entry/237-plugin-dll/

    https://www.lotus-simulator.de…ntry/236-plugin-ini-file/

  • Thanks for answering!


    I do not really understand what you mean with interface or methods in this context... Plugin dll should describe everything...?

    I mean that what functions can we use to get data from LOTUS? The plugin DLL example code contains all the functions the LOTUS can handle? Not like it wasn't enough, but I just want to make it sure.



    I do not really understand, what you mean...

    I just meant that if I want to use for example the velocity data for a speedometer via Arduino, I "export" the velocity data in the "ReceiveVarFloat()" function, since it's used for float types. So I write some code inside that function, something like exporting the value I need via serial port, HTTP, anything like that.


    Hmm, every information and also an example should be given by our two articles...

    I was just curious whether you can name any simple program that can build dll files, but I guess a simple google search will answer this question :)

  • I mean that what functions can we use to get data from LOTUS? The plugin DLL example code contains all the functions the LOTUS can handle? Not like it wasn't enough, but I just want to make it sure.

    Yes, that's currently all.

    I just meant that if I want to use for example the velocity data for a speedometer via Arduino, I "export" the velocity data in the "ReceiveVarFloat()" function, since it's used for float types. So I write some code inside that function, something like exporting the value I need via serial port, HTTP, anything like that.

    Yes, anything like that! ;-)


    I was just curious whether you can name any simple program that can build dll files

    Well, I am not a good source of information concerning that question – we do use Delphi and I know, there exists Lazarus, but that's all I know! ;-)

  • Yes, you can add comments using semi-colon ;

    \|/⠀⠀⠀ ⠀⠀⠀⠀⠀⠀⠀(__)

    ⠀⠀⠀⠀`\-------------(oo)

    ⠀⠀⠀⠀⠀||⠀⠀⠀ ⠀⠀(__)

    ⠀⠀⠀⠀⠀||w------||⠀⠀⠀⠀\|/

    ⠀⠀⠀\|/

  • I've come across some problems. To be more precise, my DLL does nothing. And since it's a DLL, not an executable file, nor the LOTUS has anything to test the plugins, I don't really know what the problem might be.


    Here are my files I compiled the dll from:

    Teloc.ini Teloc.pas Teloc_config.txt


    I don't get any more errors about the code (I'm using Free Pascal Compiler), but I don't know whether the serial connection works at least, or the game itself sees the plugin itself. I placed these (as well as the compiled DLL file) in LOTUS\Plugins. Is there any spectacular error I made that I don't see?

  • I had to change to Lazarus as well, since Free Pascal alone cannot handle message boxes...

    But I think my dll isn't even loaded into LOTUS, since I placed a ShowMessage into PluginStart and I get no pop-up window or whatever.


    Here's what my folder structure looks like. I could manage to make the Lazarus compile 32 and 64 bit versions after having fun with the settings and the FPC.

    My .ini file looks like this:


    Code
    1. [DLL]
    2. filename_32='Teloc.dll'
    3. filename_64='Teloc_64.dll'
    4. ;only velocity is used (in m/s)
    5. [ReadingVarsFloat]
    6. count=1
    7. var.0=v_Axle_mps_0_0


    Here's what my pluginStart procedure looks like:


    Here's my current .pas file I'm compiling the DLLs from:

    Teloc.pas


    I don't know if there's a point I'm missing. It's a bit hard to debug a dll as I see, though I could test the inner functions at least with another program (I could write a program that includes the DLL and then call the pluginstart, receiveVarFloat...etc to see if the serial connection works...etc, but that still doesn't make sure, if the LOTUS game itself communicates with the DLL or sees it at least).

  • Hmmm... everything seems to be ok... another test could be trying to let the DLL write into a test file some text. The ini file seems to be ok, too.


    Last but not least, I do not know, if there are problems using Lazarus... :-(


    Did you try both 32bit and 64bit?

  • It can happen that I didn't set it up properly, though it doesn't give any errors or warnings (well one warning for a non-used variable). I'm pretty new to writing DLLs, and I haven't used Lazarus before either.


    I know it's a pretty big request, but if anyone from the developer team uses Lazarus at home, could someone please compile my .pas file and send the DLLs back to see if the code is OK?

  • Hi,


    under exports you have PlugInStart and PlugInFinalize, change that to PluginStart and PluginFinalize. Then it should work



    :)

    \|/⠀⠀⠀ ⠀⠀⠀⠀⠀⠀⠀(__)

    ⠀⠀⠀⠀`\-------------(oo)

    ⠀⠀⠀⠀⠀||⠀⠀⠀ ⠀⠀(__)

    ⠀⠀⠀⠀⠀||w------||⠀⠀⠀⠀\|/

    ⠀⠀⠀\|/

  • Oh FFS... :rofl:
    You know, these are the little things I hate at work too, looking for bugs for days, then realize that it's a typo or some other idiot human error. Anyway, thanks for finding that typo!


    Now LOTUS surely sees my plugin, because now I get error messages.



    One is at startup (I got another one at loading a map, about the OnConnectVehicle but I couldn't screenshot it), and another at closing the game. Though I didn't get the ShowMessage I was waiting for (maybe that's the cause of the problem, I don't know yet). The two named functions (well, procedures), OnConnect and OnUnconnect, so they're empty inside because I don't want to use them. Should I just simply delete them from the export unit, so LOTUS doesn't even want to call them, or...?


    Also, it's not a big deal to compile the .pas file to 32 and 64 bit versions, but if I use 64bit version of LOTUS, isn't it enough if I just compile the 64 bit version over and over again? Does the LOTUS.exe even call the 32 bit version if the main program is 64 bit versioned?




    Edit: I deleted the mentioned functions from the export unit, though the cause of the error was the file read at the beginning of the Pluginstart. Now it 'works', I mean it doesn't give errors, though the serial port still doesn't. I guess I'll just try with that one more (yes, the serial comm parameters are correct, according to the arduino's manual).


    Edit #2: After a bit of searching, I found out somehow the port format in Lazarus/FPC is now ''\\.\COMx' and not 'COMx', 'COMx:' or anything logical. So...the serial port now works, but I have one problem. Since the LOTUS now sends hundreds (well, about a thousand) data per second via serial port, the program lags. I don't know if I can lower the baud rate lower than 9600bps, so is there any way in LOTUS to limit the CPU usage of the DLLs (if the values would be sent in every half second, that would be still OK for me) or the only way is up to me, by using timers or delays in the dll code?

  • The reading procedures should not contain time critical processes! They should only set variables in your DLL which will be processed by different procedures. E.g. you could add a TTimer component and use its "OnTimer" event.

  • The reading procedures should not contain time critical processes! They should only set variables in your DLL which will be processed by different procedures. E.g. you could add a TTimer component and use its "OnTimer" event.


    By the way how should I use other procedures? Is there any "main" program block where I can write code? In pascal programs the last begin - end. block acts as a main function, but the plugin itself is a library not a program. So...where should I call other procedures from?

  • Well, that depends on the task, these procedures should do?

    You said earlier that I should not do anything time relevant in the ReceiveVarFloat procedure (like I do at the moment too). I guess the proper thing would be to use the ReceiveVarFloat to set some global variables, THEN in a kind of task function (or a main loop, anything) I would use timers to handle the serial communication. So my question is, where should I write such a code?


    Sorry if it's a very beginner question, I'm just not used to write libraries, especially not in pascal. :/

  • If you like, you can create an own thread (e.g. with a child of the TThread class), else you could create a TTimer, which calls your procedure(s) in a usefull interval.

  • I've been trying to understand how I could use a TTimer in the DLL, but it looks like object pascal is too object oriented for my taste...

    Since every example I found on the internet uses some kind of forms as classes, which is not I want, I'm asking for help.


    I see that I have to set up a timer:TTimer, and I guess I initialize it in the PluginStart procedure (add interval, enable it...etc). I see that the procedure I write to handle serial ports (see above) is actually the OnTimer "event handler" of the timer. What I don't get is that how all this should look like... I add a timer as a variable globally? Should I inherit my "onTimer" event handler procedure from something, like TComponent.procedureName(something?) ? Where do I set this procedure as the onTimer property of the timer object?


    I'm sorry for asking such basic things, but I'm really not used to object pascal (or usually OOP), and to be honest I can't really use my embedded C skills here :D