The Excel 2013 XLL SDK (downloadable here), namely the header XLCALL.H and the source file XLCALL.CPP (attached to the question) allow to code a c/c++ dll (with extension xll, but it's a plain dll) exporting c/c++ function that are directly callable from Excel has soon as the xll has been registred in Excel.
I would like to be able to provide Fortran xll registrables in Excel, allowing for direct Excel call of Fortran functions. (With appropriate signatures, not everything is possible in C/C++ already, hence in Fortran also.) Since I have not found nothing related in https://software.intel.com/content/www/us/en/develop/download/776976.html , I would like to mimic XLCALL.H and XLCALL.CPP in Fortran. (I am not at all a Fortran expert at all.) They mainly rely through very simple types on headers that Windows.h includes, namely :
- WORD is a typedef for unsigned short which translates to logical*2 in Fortran
- INT23 is a typedef for signed int = int which translate to integer*4 in Fortran
- DWORD_PTR is an unsigned __int64 = long long which translate to integer*8 in Fortran
- BYTE is an unsigned char which can be translated to a logical*1 in Fortran
- LPSTR is null terminated char* which translates in Fortran to an allocatable character array
The rest is mainly structures of structures of unions, which can be translated to Fortran, would the union no contain allocatable arrays nor pointers, which is sadly the case here.
Namely, this :
will not compile with ifort, but how could I provide a type providing the same patter as the union does when I want allocatable arrays and pointer to be allowed ?
For some background discussion when it comes to UNIONs and Fortran, please see this thread:
Re: your interest in implementing user-defined functions with XLL approach in Excel, have you considered a mixed-language solution? It is rather easy with Intel Fortran and a C/C++ processor, say Microsoft C/C++, particularly in Visual Studio (VS) in conjunction with Intel Fortran integration with VS. An option with this will be a Fortran static library that has all your compute/business logic along with a thin wrapper XLL/DLL project in C/C++ that manages the data traffic, especially those involving UNION data types. You may find it much easier given your expertise in C/C++. As you may know, from C/C++ dynamic library side of the fence, you can invoke Fortran code effectively as C functions; by the way, the C interoperability in Fortran staring 2003 standard revision makes it much clearer and easier also.
Thank you for the link you provided on unions, Fortran-wise it is over my head now but I'll will try to understand it. (I don't see for now if the new type proposed provides the "same" "pattern" as a union does, while allowing for allocatable arrays (and pointers, but I won't use pointers regarding what Steve commented) or not.
Regarding the solution you propose, I tought of it and indeed think I could implement it (I already did something similar with Matlab instead of Excel), but I would really like to provide a Fortran only, as much as possible, solution.
C char * is NOT the same as Fortran allocatable character, nor are Fortran pointers the same as C pointers. For C character strings, they are interoperable with an array of single characters, and it's your responsibility to locate the trailing NUL (or insert one). The next revision of the Fortran standard will add some procedures that make this easier.
C pointers are type C_PTR (from ISO_C_BINDING) in Fortran.
Thank you for your answer Steve, I was indeed a bit carry away too fast by my optimism. So yes char* is interoperable with arrays of charecter's, '\0' left to the user. I don't know if you gave a look to the files I attached, but if you did, do you think this could be translated to Fortran ?
A quick glance doesn't spot anything that couldn't be done in Fortran, other than the unions which would be easier done with the UNION extension, but could be handled (awkwardly) with TRANSFER.
'\0' is C_NULL_CHAR from ISO_C_BINDING. The C interoperability features are quite powerful, if you understand how to use them properly.
Ok, this cheers me up. I will try to understand how the UNION "pattern" can be replaced (thanks to TRANSFER) with something achieving the same functionality, but that will allow for allocatables and pointers. I am not sure that this will be interoperable with excel though.
Does your comment on the C interoperability features mean perhaps that you wouldn't advise me to rewrite all in Fortran, but rather interface my Fortran code to the C excel api using these interoperability features ?
If there is a C Excel API (and I do mean C, not C++ - the files you provided do use 'extern "C"' so that is good), then you should be able to call it from Fortran.
Ok, but I would like to rewrite the API as Fortran Excel API, which seems to clash with the fact that "No Fortran type is interoperable with a C union type, a C structure type that contains a bit field, or a C structure type that contains a flexible array member." (Modern Fortran Explained - Incorporating Fortran 2018, p. 371.)
The original post equates ("translates to...") some of the C typedefs types with the logical Fortran type - they are better considered integer type.
The use of unions within structures (with the union preceding rather than following the component that nominates the "type" of the object represented by the structure), flexible array components, variadic functions and/or pascal calling convention make this API a bit harder to write Fortran wrappers for. A thin C interface layer is probably the best pathway forward.
To be clear - in the context of a structure component, char* in C is a C pointer to one or more char (the sequence of chars typically being terminated by a null character). It is not the sequence of char (the string) itself. Recent posts on stackoverflow still conflate a C pointer and a Fortran allocatable or Fortran pointer. Represent C pointers in structures on the Fortran side with TYPE(C_PTR). Information represented on the C side in a structure member that is a string referenced by a char*, may be best represented on the Fortran side by an allocatable CHARACTER or array, but that translation needs to be done by your interface code.
In addition to a lack of interoperability in Fortran with C UNIONs, please note there is no support for variadic arguments in Fortran when it comes to interoperability with C. Thus with API functions such as Excel12 (https://docs.microsoft.com/en-us/office/client-developer/excel/excel4-excel12)
int Excel12(int iFunction, LPXLOPER12 pxRes, int iCount, LPXLOPER12 argument1, ...);
you will need to resort to some workarounds, perhaps write generic Fortran interfaces (a la function overloads) to each combination of Excel12 invocations you anticipate or run into.
Any particular reason why you seek a Fortran-only solution?
With the teams I have worked with in the recent past, generally they have found it productive to have caller-agnostic (and thus cleaner) Fortran-only libraries that may also include functional style and which are consumed by other Fortran programs, often for heavy number-crunching on standalone basis. But then the same libraries can be wrapped in thin XLLs for use in Microsoft Excel where all the Excel datatypes, API handling and Excel callbacks, etc. are isolated in those XLLs and kept separate from the important computational codes. Interestingly this model is being followed even with migration away from Fortran to all C++ by many of these teams in that their C++ compute libraries only have scientific/engineering code, thereby introducing a level of "separation of concerns" SoC.
In your case, a separate thin wrapper layer will make it much easier than have to try to force fit the C/C++ programming constructs with Microsoft Excel datatypes and APIs into Fortran!