`
Par2: C Programming in Clarion 1998-05-18 -- Sean Wilson The Clarion development system has been shipping with a C compiler for some time and yet many people are still running into problems developing Multi-Language applications. The Programmer's Guide contains a single chapter on Multi-Language Programming which is a must read, despite the fact that it was written about 5 years ago and some of the information is no longer accurate or relevant. Multi-Language Programming deserves a detailed discussion, however this article is intended only to illustrate the most fundamental aspects of calling C code from a Clarion application. Those of you that use the Application Generator for developing every application will have to excuse the fact that I'm an unrepentant hand-coder. The Anatomy of a C++ Source File Those of you who are still conscious are probably saying "C++, why would I want to know about C++? I want to call C code!" The problem is that the 'C' compiler that ships with Clarion is really a C++ compiler. It does the same job, but there are some important differences, I won't go into all the subtle differences between C & C++, I will simply discuss those that are likely to affect the way you have to code for compatibility with Clarion. The best way to examine a programming issue is to look at some code: 1: // TSTC.C 2: #if defined(__cplusplus) 3: extern "C" { 4: #endif 5: int add(int a, int b); 6: #if defined(__cplusplus) 7: }; 8: #endif 9: 10: int add(int a, int b) 11: { return a+b; 12: } This possibly looks a little more complicated than you first anticipated, I will now describe in detail what is going on at each line of code: 1 C++ line comments begin with '//', the comment is simply to tell you what the C file in this example is called. 2 This introduces a section of conditionally compiled code. The __cplusplus macro is defined whenever a C++ compiler is being used to compile the code. 3 The extern "C" directive is used to declare a name that will use C language naming conventions. By default C++ compilers mangle or decorate names by encoding additional type information into the name to facilitate type-safe linking. This directive will disable the name-mangling and prefix the name with an underscore ('_'). 4 This terminates a section of conditionally compiled code. 5 The prototype for the C function. As it appears within the extern "C" directive the linkage name generated byt the compiler will be "_add". 7 This terminates the extern "C" directive. 10-12 The definition of the C function. Note that C++ compilers require ANSI syntax which expects the definition to be fully prototyped with the parameter types included in the parameter list. Calling C From Clarion The Clarion code is simpler to explain, particularly as you are probably quite familiar with the language, still taking a similar approach: 1:! TSTCLW.CLW 2: PROGRAM 3: 4: MAP 5: MODULE('TstC') 6: add(SIGNED a, SIGNED b), SIGNED, PROC, RAW, NAME('_add') 7: END 8: END 9: 10: CODE 11: MESSAGE(add(2,2)) This code does very little, in fact nothing useful other than to demonstrate the success of calling the add() function by displaying its' result. 5 The MODULE() statement is required to prototype externally defined procedures, however the name that appears is not used. 6 This is where the hard work is done. Note that the prototype should match exactly the C++ prototype otherwise some very odd problems will occur. Parameter prototyping errors are usually very difficult to track down. The NAME() attribute should contain the linkage name for the function which as noted before is "_add". Although it is not required for this function, it is good practice to include the RAW attribute which ensures that additional type iformation is not passed as an additional implicit parameter. I usually like to include the PROC attribute which suppresses warnings when functions are called as procedures. Putting it all Together The only thing missing is the project file, this couldn't be simpler and is easily created in the Clarion IDE. I have included it here for completeness but it deserves no additional explanation: -- tstc #noedit #system win32 #model clarion dll #pragma debug(vid=>full) #compile tstclw.clw #compile tstc.c #link tstc.exe And Finally... That's it! Nothing simpler really, however I realise I have only scratched the surface here. If there are specific issues that you would like to see addressed then let me know, I will gladly incorporate new information into future articles. Printed November 23, 2024, 2:22 am This article has been viewed/printed 35358 times. |