Search code examples
c++windowsox

How to write to a dll-created file in Ox?


I'm trying to write via the native fprint() ox function to a file created in an external c++ dll.

My C++ code is (inspired by the src code of the GnuDraw Package of C. Bos) :

#define OxSetOpenFile(pv,i,d,f) (pv)[i].type = OX_FILE, (pv)[i].t.ioval.fp = d, (pv)[i].t.ioval.fmode = f
extern "C" void OXCALL fopen_C(OxVALUE *rtn, OxVALUE *pv, int cArg)
{
    char *sFile;
    FILE *fh;

    if (cArg != 1)
        OxRunError(ER_ARGS, NULL);

    OxLibCheckType(OX_STRING, pv, 0, 0);
    sFile = OxStr(pv, 0);
    fh = fopen(sFile, "w");

    if (fh == NULL)
        OxRunErrorMessage("Oops, I can't open the file");
    OxSetOpenFile(rtn, 0, fh, 162); //162 is found in the gnudraw src code 
}

I build the dll with Visual Studio 2015, however I can't write from ox to this file , the following Ox code crash at the fprint() function:

main()
{                        
    decl fh = fopen_C("test.txt");  
    if(!isfile(fh))
        oxrunerror("not file", 0);

    fprint(fh, "test text");  /// crash here
}

I got the following error message : "Debug Assertion Error" in close.cpp Expression (_osfile(fh) & FOPEN) .

I found a similar post ( here ) but the answer (to use /MTd or /MDd -ie change the runtime) doesn't work. I can overcome this issue by creating a new fprintf function in C and calling it form Ox ( it works) but I would prefer to use the native ox fprint function. I think this problem can be linked to this one, and finally to the following question: how to pass a file pointer from c to ox in windows ?


Solution

  • Finally I think that it is not possible and this is caused by the so called Dll boundaries restriction : Files handles are implemented differently accordingly the C-Run-time library used at compilation time. Obviously I can pass the file pointer but the structure of the file handle (its CRT structure) is not recognised by Ox.

    Then, unless my dll is compiled against the exact same version of the C Run-time library used to compile ox, it will not works. This could be overcome by linking dynamically with the C library but since the official ox dll (oxwin.dll) is compiled with static linkage (as illustrated in the header “Ox Professional version 7.10 (Windows_64/U/MT)” ) it is not an option. So no matter which option I use to compile my DLL, Ox will always have its own copy of the CRT library and its own heap manager.

    Finally I think the best way to write to a file open in a external dll (for windows) is to create a new C function : fprint_dll() located in the same dll as the one which open/close the file and to call it from ox.

    Basically to not perform I/O operations with the file handle outside of its "native" dll.

    See also :

    https://support.microsoft.com/en-us/kb/140584

    C Runtime objects, dll boundaries