[SOLVED] C call-in using API

Author: roman.schroeder@team-w.ch (labmouse)

Hi all, I am very new to Uniface. Currently playing around it with Uniface 9.6 win_x86 and and its functionality.   Basically, I have a very dummy C executable that should call-in Uniface. Unfortunately, all my experiments are failed. So I hope someone can help me... === MS VS 2015 === #include "stdafx.h" #include <h3gl.h> int main() {     printf("Hello world ");     unsigned char ver[20], trk[20], pat[20], pla[20], dat[20], opr[20];     int maj, min, mic;     uversioninfo(ver, trk, pat, pla, dat, opr, &maj, &min, &mic);     printf("version: %d.%d.%d ", maj, min, mic);     printf("?: %s ", ver);     printf("?: %s ", trk);     printf("?: %s ", pat);     printf("?: %s ", pla);     printf("?: %s ", dat);     printf("?: %s ", opr);     return (UACT_SUCCESS); } Compiler and Linker go through, but execiting the code I get: "Number 575 is not found in ULIB.DLL"... any idea what is missing?   Another example is with GCC #include <stdio.h> #include <stdlib.h> #include <h3gl.h> int main(void) {     printf("= Hello World ");     unsigned char ver[20], trk[20], pat[20], pla[20], dat[20], opr[20];     int maj, min, mic;     uversioninfo(ver, trk, pat, pla, dat, opr, &maj, &min, &mic);     printf("version: %d.%d.%d ", maj, min, mic);     printf("?: %s ", ver);     printf("?: %s ", trk);     printf("?: %s ", pat);     printf("?: %s ", pla);     printf("?: %s ", dat);     printf("?: %s ", opr);     return (UACT_SUCCESS); } compiler and linked also fine, but when executing: bad exit value... nothing. any help / hints are very welcome!   Best, labmouse

9 Comments

  1. Hey labmouse, The CHM help file contains a number of examples calling / starting Uniface from a 3gl. Looking at your code, I don't see any calls to either unifbeg or uecreate - and as far as I know, one of the two has to be called first to 'initiate' the Uniface runtime environment. Regards, Knut


    Author: Knut (knut.dybendahl@gmail.com)
  2. Hi Knut, thx for reply. Thx for hint, I have read docs here-<uecreate> and here-<uversioninfo>. uversioninfo does not require an instance, accordingly to the documentation. Anyway, the example with uecreate, ends with same error - with gcc and msvs2015. Therefore, the question is if something special is required - include and linking should be correct -> otherwise I would be not able to compile. Something is wrong during the run time...


    Author: labmouse (roman.schroeder@team-w.ch)
  3. Knut is correct. You need to execute (e.g.) uecreate first and when you got a valid Uniface environment handle then you can call uversioninfo. The error “Ordinal Number 575 is not found in ULIB.DLL”, however, is caused by something else: your C executable is loading the "incorrect" ulib.dll. Windows also has a module called ulib.dll. And in case the ulib.dll of Uniface is not located in the same directory as your c executable then it will load the ulib.dll from Windows. Hope this helps. Regards, Daniel


    Author: diseli (daniel.iseli@uniface.com)
  4. It's probably true that uversioninfo() requires an instance to work. Although it's not mentioned, and actually I would not expect it because the information is hardcoded data in the yrtl/urtl. However I get ordinal errors either way, with or without an instance, and not related to the Windows version of urtl.dll. Not sure what's happening here. But I guess uversioninfo() is not your actual need ? If you're just looking for a quick-start with the call-in API, here's an absolutely minimal source that works. It activates operation OPER in service S120881, passing the input parameter "123". #include "h3gl.h" #define ASN "idf.asn" #define SVC "S120881" #define OPR "OPER" void main () { UHACT hEnv, hIn, hOp; long i, j; uecreate(1, 0, 0, ASN, 0, 0, &hEnv); uinstnew (hEnv, (UCHAR *)SVC, 0, 0, UDEFAULT_COMM_MODE, 0, &hIn, &i); uinstopr(hIn, (UCHAR *)OPR, 0, &hOp); ustr2uf (hOp, 1, "123"); uopract (hOp, &i, &j); ufreeh(&hOp); uinstdel(hIn, 0); ufreeh(&hIn); ufreeh(&hEnv); }   No comments or error checking, but the very essence of brevity ! See if this helps you along. Compile and link as follows: call "c:\Program Files (x86)\Microsoft Visual Studio 8\Vc\bin\vcvars32.bat" cl /c /I%USYS%\uniface\3gl\include 3gl.c link /out:3gl.exe 3gl.obj %USYS%/uniface\3gl\lib\ucall.lib Chris Breemer


    Author: Chris Breemer (chris.breemer@uniface.com)
  5. Chris Breemer said It's probably true that uversioninfo() requires an instance to work. Although it's not mentioned, and actually I would not expect it because the information is hardcoded data in the yrtl/urtl.

    I've tested this and when I call uversionfo without uecreate then the function returns "rubbish". Only when I use uecreate first then uversionfo will return the expected values. I guess the doc is not accurate here.

    Chris Breemer said However I get ordinal errors either way, with or without an instance, and not related to the Windows version of urtl.dll. Not sure what's happening here.

    When I copy the program into the usysbin directory then it runs without problems. When I, however, run it from a directory where no ulib.dll from Uniface is present then I also get the ordinal error(s). I'm not 100% sure, but I think the ordinal error is caused when the ulib.lib of Uniface is linked into your program. This seems to cause a dependency to the ulib.dll, which the program wants to load at startup. And depending on which ulib.dll is loaded first (the one from Windows or the one from Uniface) the ordinal error is thrown or the program works. Daniel


    Author: diseli (daniel.iseli@uniface.com)
  6. Chris Breemer said No comments or error checking, but the very essence of brevity ! See if this helps you along. Compile and link as follows: call "c:\Program Files (x86)\Microsoft Visual Studio 8\Vc\bin\vcvars32.bat" cl /c /I%USYS%\uniface\3gl\include 3gl.c link /out:3gl.exe 3gl.obj %USYS%/uniface\3gl\lib\ucall.lib

    @Chris: thx for example and compile instructions. There is still a problem with ulib - executable works only if it is located in %USYS%/common/bin . @Daniel: also many thx for investigations   As Daniel Diseli wrote:

    diseli said And in case the ulib.dll of Uniface is not located in the same directory as your c executable then it will load the ulib.dll from Windows.

    => GCC: coping DLL into a custom folder with executable will not work either.

    diseli said When I copy the program into the usysbin directory then it runs without problems.

    => GCC: works

    diseli said I'm not 100% sure, but I think the ordinal error is caused when the ulib.lib of Uniface is linked into your program. This seems to cause a dependency to the ulib.dll, which the program wants to load at startup. And depending on which ulib.dll is loaded first (the one from Windows or the one from Uniface) the ordinal error is thrown or the program works.

    => GCC: strange. I also have compiled without linking to ulib and still same behaviour as described above.   --- regarding MVS: works out of the box, but %USYS%/common/bin must be in PATH   Summary:

    • strange behaviour on Win-box with GCC compiler: ulib issue.
      • GCC tests on Linux-Box are tbd.
    • MVS is OK, but PATH to Uniface-ulib must be set correctly.
    • issues above are independent from the fact if a program is linked to ulib or not.

    Thanks!


    Author: labmouse (roman.schroeder@team-w.ch)
  7. Good to hear that you got it working. In the meantime I've also found the following post with a better "workaround" (i.e. solution):

    palm.kevin said Just to complete this issue: I found out how run the call-in application without having to copy it to the Uniface-bin folder. The initial problem is that, on runtime, the application loads the ulib.dll contained in the Windows system32 folder instead of the one contained in the Unfiface/Common/bin folder. To prevent this, I discovered the following solution (others exist...):
    1. When linking, add uniface libraries to list of dynamically loaded libraries (with Visual C++: /DELAYLOAD:"ulib.dll" /DELAYLOAD:"yrtl.dll" /DELAYLOAD:"ucall.dll" /DELAYLOAD:"urtl.dll")
    2. Then, at the beginning of the main function of your application, define the folder where dlls should be searched first: SetDllDirectory(_T("C:\\Uniface9401\\common\\bin\\"));
    3. That's it

      Hope this helps. Daniel


    Author: diseli (daniel.iseli@uniface.com)
  8. Two remarks on the above discussion. 1) In my experience the call-in executable does not need to be in the Uniface bin folder. You can have it anywhere provided you put the Uniface bin folder high up in your PATH variable, i.e. before the System32 folder. 2) I think it's stated in the documentation that we only support the native vendor compilers. Certainly this is mentioned for Unix, and if it's not mentioned for Windows it should be. Ergo, we've never tested with GCC or MVS. I'm sure things can be made to work with these but it may need some tweaking. Actually with Visual Studio Express being free there seems no need to use 3rd party compilers on Windows. Cheers, Chris Breemer


    Author: Chris Breemer (chris.breemer@uniface.com)
  9. Thanks a lot Daniel for this info (and repost)... now it perfectly makes sense. Especially the "Remarks" section of SetDllDirectory function on msdn helped a lot. Zdeněk


    Author: sochaz (zdenek.socha@fullsys.cz)