FORTRAN DLL calling convention from MapleSim / Modelica - dll

Modelica modeling language supports calling functions from external FORTRAN DLLs, however, MapleSim only includes the support of calling functions from C DLLs even though it says it has full support for the Modelica language, and I have no choice but to use this FORTRAN DLL (I can't reprogram it in C nor I can use other Modelica evironments than MapleSim), so I'm not in the undocumented features realm.
I tried forcing MapleSim to include the FORTRAN DLL and created a custom component but its not working. This is the code I got when I opened the custom component: [relevant portion only]
model ExternalCode
function GETPSAT
input Real TC;
output Real PC;
external "C" PC = GETPSAT(TC)
annotation (
Library = "C:/Path/To/My/DLL/FORTRAN.dll", __Maplesoft_callconv = "stdcall");
end GETPSAT;
equation
(PC) = GETPSAT(TC);
annotation (
experiment(__Maplesoft_engine = 2));
end ExternalCode;
I know I should change external "C" to external "FORTRAN", but what should I should I do with __Maplesoft_callconv = "stdcall"? ie: what is the call convention for FORTRAN functions? (I know nothing on the subject of calling conventions).
Note the parent evnironment of MapleSim 6.1 (Maple 17) supports importing external functions from FORTRAN so I think there is a possibility MapleSim will support it despite it being undocumented.
edit: By the way, the DLL was compiled with Compaq visual fortran (I don't remember the version)
edit2: The function in the FORTRAN DLL is exported as follows:
FUNCTION GETPSAT(TC)
!DEC$ ATTRIBUTES ALIAS:'GETPSAT' :: GETPSAT
!DEC$ ATTRIBUTES DLLEXPORT :: GETPSAT
!DEC$ ATTRIBUTES VALUE :: TC
GETPSAT=PSAT11(TC)
RETURN
END
edit3: I don't know it this helps, but the same function can be called from C# like this:
[DllImport("C:\\Path\\To\\My\\DLL\\FORTRAN.dll")]
static extern float GETPSAT(float T);

This particular Fortran function should behave like a completely normal C function because of the attributes it has. Do not add any external(FORTRAN) or similar. Its name should be GETPSAT and it accepts 1 float TC by value.
Use the same "stdcal" attribute, it is default for the DEC, Compaq and Intel Fortran https://software.intel.com/sites/products/documentation/hpc/mkl/mkl_userguide_win/GUID-E74229B0-7389-46A6-9FCF-91CD6CD5B0E4.htm

Related

How to get process id in Ada?

I want to make a method returning the calling process id, but can't seem to find how to do that in Ada. Must be looking in the wrong places.
How to get process id on windows and POSIX platforms?
The Florist binding to POSIX should work, but it is quite a sizeable library. Here is a simpler binding example, tested on Mac OS-X:
with Ada.Text_IO;
with Interfaces.C;
procedure My_Pid
is
function Get_Pid return Interfaces.C.int
with Import, Convention => C, External_Name => "getpid";
begin
Ada.Text_IO.Put_Line (
"My PID is" & Interfaces.C.int'Image (Get_Pid));
end My_Pid;
This assumes that the POSIX type pid_t, defined in <unistd.h>, is compatible with Interfaces.C.int, which may not hold on all POSIX platforms; the alternative AIUI is Interfaces.C.long.
I don't have access to a Windows system to test, but it seems there is a _getpid function (https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/getpid?view=msvc-170), with getpid (no leading underscore) as a deprecated alias (https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/posix-getpid?view=msvc-170).
There is also an extensive binding to the Win32 API, similar in scope to Florist, at https://github.com/AdaCore/win32ada.

What do curly braces inside a function's argument list mean in C? [duplicate]

This code:
#include <stdio.h>
int main()
{
void (^a)(void) = ^ void () { printf("test"); } ;
a();
}
Compile without warning with clang -Weverything -pedantic -std=c89 (version clang-800.0.42.1) and print test.
I could not find any information about standard C having lambda, also gcc has it's own syntax for lambda and it would be strange for them do this if a standard solution existed.
This behavior seems to be specfic to newer versions of Clang, and is a language extension called "blocks".
The Wikipedia article on C "blocks" also provides information which supports this claim:
Blocks are a non-standard extension added by Apple Inc. to Clang's implementations of the C, C++, and Objective-C programming languages that uses a lambda expression-like syntax to create closures within these languages. Blocks are supported for programs developed for Mac OS X 10.6+ and iOS 4.0+, although third-party runtimes allow use on Mac OS X 10.5 and iOS 2.2+ and non-Apple systems.
Emphasis above is mine. On Clang's language extension page, under the "Block type" section, it gives a brief overview of what the Block type is:
Like function types, the Block type is a pair consisting of a result value type and a list of parameter types very similar to a function type. Blocks are intended to be used much like functions with the key distinction being that in addition to executable code they also contain various variable bindings to automatic (stack) or managed (heap) memory.
GCC also has something similar to blocks called lexically scoped nested functions. However, there are some key differences also note in the Wikipedia articles on C blocks:
Blocks bear a superficial resemblance to GCC's extension of C to support lexically scoped nested functions. However, GCC's nested functions, unlike blocks, must not be called after the containing scope has exited, as that would result in undefined behavior.
GCC-style nested functions also require dynamic creation of executable thunks when taking the address of the nested function. [...].
Emphasis above is mine.
the C standard does not define lambdas at all but the implementations can add extensions.
Gcc also added an extension in order for the programming languages that support lambdas with static scope to be able to convert them easily toward C and compile closures directly.
Here is an example of extension of gcc that implements closures.
#include <stdio.h>
int(*mk_counter(int x))(void)
{
int inside(void) {
return ++x;
}
return inside;
}
int
main() {
int (*counter)(void)=mk_counter(1);
int x;
x=counter();
x=counter();
x=counter();
printf("%d\n", x);
return 0;
}

Compaq Visual Fortran 6.6, Dynamic-Link Library (DLL) and Module

I need to create and use dynamic-link library (DLL) for Fortran application using Compaq Visual Fortran 6.6. The following code works just fine:
PROGRAM AMAIN1
IMPLICIT NONE
REAL(8):: A,B,S
A = 1D0
B = 2D0
CALL SUBRO1(A,B,S)
PRINT*, 'S = ', S
END PROGRAM AMAIN1
SUBROUTINE SUBRO1(A,B,S)
!DEC$ ATTRIBUTES DLLEXPORT :: SUBRO1
IMPLICIT NONE
REAL(8):: A,B,S
S = A + B
RETURN
END SUBROUTINE SUBRO1
The result is correct:
S = 3.00000000000000
Press any key to continue
However, if I implement the same algorithm using the module, I get inconsistent result (i.e. zero):
PROGRAM AMAIN2
USE MODUL2
A = 1D0
B = 2D0
CALL SUBRO2
PRINT*, 'S = ', S
END PROGRAM AMAIN2
MODULE MODUL2
IMPLICIT NONE
REAL(8):: A,B,S
END MODULE MODUL2
SUBROUTINE SUBRO2
!DEC$ ATTRIBUTES DLLEXPORT :: SUBRO2
USE MODUL2
S = A + B
RETURN
END SUBROUTINE SUBRO2
The result is incorrect:
S = 0.000000000000000E+000
Press any key to continue
As can be seen above, DLL contains only subprogram in both cases (SUBRO1 and SUBRO2, respectively). I have built DLL and LIB files from the visual development environment. The second case (with the use of module) represents the structure of my large source-code so I need to resolve this issue. Any advice would be greatly appreciated.
BTW, the same algorithm without using the DLL works well and gives correct result:
PROGRAM AMAIN3
USE MODUL3
A = 1D0
B = 2D0
CALL SUBRO3
PRINT*, 'S = ', S
END PROGRAM AMAIN3
MODULE MODUL3
IMPLICIT NONE
REAL(8):: A,B,S
END MODULE MODUL3
SUBROUTINE SUBRO3
USE MODUL3
S = A + B
RETURN
END SUBROUTINE SUBRO3
The result is correct:
S = 3.00000000000000
Press any key to continue
You need to add:
!DEC$ ATTRIBUTES DLLEXPORT :: A,B,S
to the module, so that the main program can see the module variables from the DLL. Otherwise A, B and S are local variables.
Edit: January 16, 2019
I was able to log in to Bakhbergen's PC and eventually figured out the problem.
In CVF 6.6C (and the later Intel compilers), when you USE a module that has a DLLEXPORT directive, that turns into a DLLIMPORT, hence my advice above. But it wasn't always this way, and the version he has doesn't have that behavior. Before that change (which my memory says I lobbied for), you had to supply a separately compiled .mod where the source had DLLIMPORT instead of DLLEXPORT. When I did this, the program worked. I don't remember exactly which update had this change.
So what he needs to do is have two versions of MODUL2.f90, one with DLLEXPORT and one with DLLIMPORT. The DLLEXPORT version gets built into the DLL. The DLLIMPORT version would just be compiled (/c) and only the .mod used, not the ,obj, when linking the main program. Messy, I know, which is why we changed it.

How to load DLL file from Jscript file?

So I'm writing a standalone JScript file to be executed by Windows Script Host (this file is not going to be used as a web application).
My goal is to load a dll file. Just like using LoadLibrary function in a C++ application.
I tried researching the subject but I didn't come up with anything useful. I'm so lost I don't have any piece of code to share. I understand using ActiveXObject may come to my rescue. if so, any idea how to use it?
Update:
If we all agree that loading is impossible, I'll settle for validity check. Meaning, don't try to load but check if it is loaded and functional.
You can export a specific function for this purpose.
Then, from your JScript, execute rundll32.exe and check that the function ran as expected.
You might also give Gilles Laurent's DynaWrap
ocx a chance.
This kind of dll needs to be registered on the target system like regsvr32 /s DynaWrap.dll.
It is restricted to 32-bit DLLs, and this might be inconvenient for you to use, but it works on a 64bit Windows. You can't access function exported by ordinal number and you can't directly handle 64bit or greater values/pointers.
Here's a sample to call MessageBoxA from JScript:
var oDynaWrap = new ActiveXObject( "DynamicWrapper" )
// to call MessageBoxA(), first register the API function
oDynaWrap.Register( "USER32.DLL", "MessageBoxA", "I=HsSu", "f=s", "R=l" )
// now call the function
oDynaWrap.MessageBoxA( null, "MessageBoxA()", "A messagebox from JScript...", 3 )
And here from VBScript:
Option Explicit
Dim oDynaWrap
Set oDynaWrap = CreateObject( "DynamicWrapper" )
' to call MessageBoxA(), first register the API function
UserWrap.Register "USER32.DLL", "MessageBoxA", "I=HsSu", "f=s", "R=l"
' now call the function
UserWrap.MessageBoxA Null, "MessageBoxA()", "A messagebox from VBScript...", 3
To use a function you need to "register" the exported function of your DLL.
To do this you need to call the register method with a first parameter containing a string object to the complete path of the DLL, a second parameter for the exported name of the function to use, and following three paremeters describing the functions declartion in a somehow obscure syntax.
i= describes the number and data type of the functions parameters.
f= describes the type of call: _stdcall or _cdecl. Default to _stdcall.
r= describes the return values data type.
The supported data types are:
Code Variant Description
a VT_DISPATCH IDispatch*
b VT_BOOL BOOL
c VT_I4 unsigned char
d VT_R8 8 byte real
f VT_R4 4 byte real
h VT_I4 HANDLE
k VT_UNKNOWN IUnknown*
l VT_I4 LONG
p VT_PTR pointer
r VT_LPSTR string by reference
s VT_LPSTR string
t VT_I2 SHORT
u VT_UINT UINT
w VT_LPWSTR wide string
Thus the Register method call used in the examples describes MessageBoxA like this:
_stdcall LONG MessageBoxA( HANDLE, LPSTR, LPSTR, UINT );
For a explanation of MessageBoxA look at the docs on MSDN.
Please read the DynaWrap docs for more sophisticated examples... But you might need Google translate, 'cos they are written in french ;-)
To be able to use a dll as ActiveXObject, it needs to be registered as COM object. There are some restrictions on this but if you have a code for this dll, it is certainly doable.
When you register your dll as COM object, it is assigned a name. You use this name to create an object. This example from MSDN uses excel since it is already registered if you installed office.
var ExcelApp = new ActiveXObject("Excel.Application");
var ExcelSheet = new ActiveXObject("Excel.Sheet");
// Make Excel visible through the Application object.
ExcelSheet.Application.Visible = true;
// Place some text in the first cell of the sheet.
ExcelSheet.ActiveSheet.Cells(1,1).Value = "This is column A, row 1";
// Save the sheet.
ExcelSheet.SaveAs("C:\\TEST.XLS");
// Close Excel with the Quit method on the Application object.
ExcelSheet.Application.Quit();
Apart from restriction of registering dll, using dll is no different from using it as c++ or c# dll. Note that, C# (or other .NET dlls) should be ComVisible to be used from javascript this way.
EDIT: The only other way of using C/C++ dll from javascript is swig interfaces. I have not used it, therefore I can only point you in that direction.
SWIG is a software development tool that connects programs written in
C and C++ with a variety of high-level programming languages. SWIG is
used with different types of target languages including common
scripting languages such as Javascript, Perl, PHP, Python, Tcl and
Ruby.

Possible to Pass an Object as a Parameter to a Fortran Method?

I'm currently working on being able to import a DLL written in Fortran into Visual Basic. I've got all the basics down, so now I'm trying to take it a step further. The title basically says it all, but I'll explain what it is I'm trying to do anyways.
For kicks and giggles, let's just assume I want to pass an object that has three double values in it, possibly representing a point in space in three dimensions. In my Fortran method, I want to take that object, print out the x value, then change the x value to 7.5. Here's my Fortran code that does just that.
module test
type Point
double precision x, y, z
end type Point
end module test
function ex1(ThreeDubs)
use test
type (Point) :: ThreeDubs
print *, ThreeDubs%x
ex1 = 1
return
end function
And this code works great!...For structures only. In other words, Let's assume I have the following structure and class in VB
Public Structure StructurePoint
Public x As Double
Public y As Double
Public z As Double
End Structure
Public Class ObjectPoint
Public x As Double
Public y As Double
Public z As Double
End Class
Creating an instance of StructurePoint yields perfect results: the Fortran method prints out the x value, and then modifies the value of x. Perfect. Now the problem. When I pass an instance of ObjectPoint, the program prints out a value similar to 1.523E-306. Basically, telling me that the location in which it thinks the x value is located is not the x value. So, herein lies my question. Is it even possible to pass an Object to a Fortran DLL and access it correctly, and if so, how would I go about doing so?
The Solution
Modifying the Class declaration is the ONLY thing that has to be done in order to pass this object to Fortran.
<StructLayout(LayoutKind.Sequential)> _
Public Class CustomPoint3d
Public x As Double
Public y As Double
Public z As Double
End Class
<DllImport("passPoint3d.dll")> _
Public Shared Function PrintX(ByVal point As CustomPoint3d) As Boolean
End Function
This might be difficult, and I don't think there's any benefit, so I advise you not to bother!
Here goes anyway! I think the VB.Net object will be marshalled as a pointer. There is some support for pointers in Fortran 90. It might work if you add pointer to the Fortran declaration of ThreeDubs.
function ex1(ThreeDubs)
use test
type (Point), pointer :: ThreeDubs ! Note additional pointer keyword
print *, ThreeDubs%x
ex1 = 1
return
end function
I doubt you would ever be able to call methods in the ThreeDubs object from the Fortran, so I'm not sure of the benefit of passing an object.
Here are two articles on PInvoke: PInvoke is the .Net name for calling oldschool "unmanaged" DLLs like your Fortran. The articles explain how .Net arguments are "marshalled" (translated) into the Fortran DLL. You have some control over the marshalling using attributes: the articles explain more. They tend to use C and C# for examples :(
I don't know about Visual Basic, but I've shared user-defined types between Fortran & C. This is supported by the ISO C Binding of Fortran 2003, which is already widely supported by Fortran 95 compilers. You declare a Fortran user-defined type and give it the bind C attribute and a bind name. As long as all of the sub-components of the type are inter-operable with C, then the user-defined type is also inter-operable with C. And this method is standard and portable. I've done this by passing the information with the Fortran user-defined type variable being a module variable, and the C structure variable being in global memory via being declared at the top of a file. Perhaps you can use the ISO C Binding on the Fortran side, and somehow tell Visual Basic to use a C-like interface?