calling an external C program from QB64 & getting back results?
#1
Some background: 
I'm working on some C code to read separate input from 2 or more USB mice plugged into the PC. That will be its own EXE file (unless it should be a DLL or something?), and when called, it looks for command line parameters. If no command line param is sent, it just returns the count of how many mice are connected to the system Else the command line parameter contains the index of the mouse to return input from, and it returns 2 numbers dx and dy, maybe just the two numbers separated by a comma, e.g. "{dx},{dy}".

I know the SHELL command can be used to call an external EXE from QB64, and theoretically you should be able to pipe the output of the EXE to a file, and read that from QB64. This is a very rudimentary method to get the two programs talking, and it seems like a very inefficient way to do it. Moreover, it doesn't seem to be working - the SHELL command in the test program doesn't seem to be redirecting the output correctly to a file, I am seeing a file not found error.

Would anyone have any ideas about a better way to do this, or even why the SHELL command isn't piping the output to a file?

Below is my QB64 program, followed by the external C program it is calling, which can be compiled to EXE using QB64 using included the batch file. (The attached ZIP has the precompiled EXEs and the source.)

Any help appreciated!


The main program "my_qb64_program.bas":

Code: (Select All)
' CALL AN EXTERNAL PROGRAM AND GET BACK SOME RESULTS
' IS SHELL AND REDIRECTING OUTPUT TO A FILE THE BEST WAY
' OR IS THERE A MORE DIRECT METHOD?

_Title "Talk to EXE from QB64"
Const FALSE = 0
Const TRUE = Not FALSE
Dim Shared m_ProgramPath$: m_ProgramPath$ = Left$(Command$(0), _InStrRev(Command$(0), "\"))
Dim sExePath As String
Dim sOutPath As String
Dim sParams As String
Dim sCommand As String
Dim sResult As String

' BUILD COMMAND LINE FOR SHELL, DIRECT OUTPUT TO FILE sOutPath
sExePath = m_ProgramPath$ + "my_c_program.exe"
sOutPath = m_ProgramPath$ + "my_c_program_output.txt"
sParams = "1 2 3"
'sCommand = Chr$(34) + sExePath + Chr$(34) + " " + sParams + " > " + Chr$(34) + sOutPath + Chr$(34)
sCommand = Chr$(34) + sExePath + " " + sParams + Chr$(34) + " > " + Chr$(34) + sOutPath + Chr$(34)

' CALL THE EXE WITH SOME COMMAND LINE PARAMETERS
Cls
Print "Shell _Hide " + sCommand: Print
Shell _Hide sCommand

' RETRIEVE THE OUTPUT <- IS THERE A MORE EFFICIENT WAY THAN USING A FILE?
Print "Output should be in file:"
Print Chr$(34) + sOutPath + Chr$(34): Print
sResult = ReadFile$(sOutPath, "(file not found)")

' SHOW RESULTS
Print "Contents of output file:"
Print Chr$(34) + sResult + Chr$(34): Print

' DONE
End

' /////////////////////////////////////////////////////////////////////////////
' Fastest way is always to just read the whole life at once and then parse it.

Function ReadFile$ (sFileName As String, sDefault As String)
    Dim x$
    If _FileExists(sFileName) Then
        Open sFileName For Binary As #1
        x$ = Space$(LOF(1))
        Get #1, 1, x$
        Close #1
        ReadFile$ = x$
    Else
        ReadFile$ = sDefault
    End If
End Function ' ReadFile$

The second program, "my_c_program.c":
Code: (Select All)
/******************************************************************************
Test to see how QB64 can call a C program with some command line arguments,
and get back some results.
******************************************************************************/
#include <stdio.h>
#include <string.h>

int main (int argc, char* argv[])
{
    printf("%s", "result:");
    for (int x=1; x < argc; ++x)
    {
        if (x > 1)
        {
            printf("%s", ",");
        }
        printf("%s", argv[x]);
    }
    return 0;
} // main

The batch file "COMPILE_C_PROG.BAT" that will compile the above C code for you using QB64's built in C compiler 
(edit line 13 to point to the QB64 directory on your PC):
Code: (Select All)
@echo off

:: %QB64DIR%      = C:\Users\maduser\Documents\Code\qb64
:: %MGWDIR%       = C:\Users\maduser\Documents\Code\qb64\internal\c\c_compiler
:: %PATH%         = C:\Users\maduser\Documents\Code\qb64\internal\c\c_compiler\bin
:: %LIBRARY_PATH% = C:\Users\maduser\Documents\Code\qb64\internal\c\c_compiler\x86_64-w64-mingw32\lib
:: %CPATH%        = C:\Users\maduser\Documents\Code\qb64\internal\c\c_compiler\x86_64-w64-mingw32\include

:: PUT THE NAME OF YOUR PROGRAM TO COMPILE HERE
SET PROGNAME=my_c_program

:: QB64DIR MUST POINT TO YOUR QB64 DIRECTORY, LIKE THIS: SET QB64DIR=C:\PROG\QB64
SET QB64DIR=C:\Users\maduser\Documents\Code\qb64

if not "%QB64DIR%"=="" goto doit
ECHO.
ECHO.
ECHO Edit line 4 of this batch file and set QB64DIR to point to your QB64 directory!
ECHO.
ECHO.
GOTO lunch


:doit
:: set up environment vars for direct invocation of QB64's included MinGW C/C++ compiler....

:: WE'LL SKIP THE SETUP IF WE'VE BEEN THROUGH THIS BEFORE....
:: WE'LL USE THE PRESENCE OR ABSENCE OF MGWDIR TO TELL US IF WE'VE PREVIOUSLY SET THE ENVARS.
:: IF MGWDIR ALREADY EXISTS, THEN SKIP THE SETUP SO WE DON'T KEEP ADDING THE SAME
:: STUFF TO THE PATH ENVAR OVER AND OVER EVERY TIME WE RUN THIS BATCH FILE....
if not "%MGWDIR%"=="" goto work


:: SET MGWDIR TO POINT TO MINGW IN OUR QB64 INSTALLATION DIRECTORY.
:: (THIS BATCH FILE SHOULD BE IN THE MAIN QB64 DIRECTORY)....
set MGWDIR=%QB64DIR%\internal\c\c_compiler


set PATH=%MGWDIR%\bin;%PATH%
set LIBRARY_PATH=%MGWDIR%\x86_64-w64-mingw32\lib
set CPATH=%MGWDIR%\x86_64-w64-mingw32\include


:work
:: NOTE: THE LINE BELOW IS SET TO PRODUCE A 32-BIT EXECUTABLE.
:: REPLACE -m32 WITH -m64 TO GENERATE 64-BIT EXEs
:: (OR REMOVE THE -m OPTION ENTIRELY TO GENERATE THE COMPILER DEFAULT)....
gcc -Wall -Os -s -m32 --static -o "%~dp1%PROGNAME%.exe" "%~dp1%PROGNAME%.c"

:lunch
pause


Attached Files
.zip   qb64_talk_to_another_exe.zip (Size: 657.73 KB / Downloads: 28)
Reply


Messages In This Thread
calling an external C program from QB64 & getting back results? - by madscijr - 09-07-2022, 05:56 PM



Users browsing this thread: 4 Guest(s)