Make external functions accessible for other functions/modules in Fortran - interface

I am new in Fortan and have a question regarding using make callback-functions available for the whole fortran-code.
I am writing on a interface which accesses a Fortran DLL from C#.
module csWrapper
interface
subroutine vdiTestFuncCllBak(inputValue, retValue)
INTEGER, INTENT(IN) :: inputValue
INTEGER, INTENT(INOUT) :: retValue
end subroutine
end interface
procedure(vdiTestFuncCllBak), pointer :: m_vdiTestFuncCllBak
end module csWrapper
module VdiFunctionRunnerMain
use csWrapper
implicit none
contains
integer function VdiFunctionRunner (XTGA, ARRAY_810, vdiCwertCllbak, vdiIwertCllbak, vdiRwertCllbak, vdiCwert2Cllbak, vdiIwert2Cllbak, vdiRwert2Cllbak, vdiErsterCllBak, vdiLetzterCllBak, vdiTestFuncCllBak)
!DEC$ ATTRIBUTES DLLEXPORT ::VdiFunctionRunner
!DEC$ ATTRIBUTES REFERENCE :: XTGA, ARRAY_810, vdiCwertCllbak, vdiIwertCllbak, vdiRwertCllbak, vdiCwert2Cllbak, vdiIwert2Cllbak, vdiRwert2Cllbak, vdiErsterCllBak, vdiLetzterCllBak, vdiTestFuncCllBak
implicit none
external vdiCwertCllbak, vdiIwertCllbak, vdiRwertCllbak, vdiCwert2Cllbak, vdiIwert2Cllbak, vdiRwert2Cllbak, vdiErsterCllBak, vdiLetzterCllBak, vdiTestFuncCllBak
!procedure(vdiErsterCllBak), pointer :: m_vdiErsterCllBak
CHARACTER (len=256) XTGA
CHARACTER (len=256) TGA, ARRAY_810(10), retValue, satzArt, satzArt2
CHARACTER (len=256) :: cWertCallBackRet
integer :: nrReturnValues = 1
m_vdiTestFuncCllBak => vdiTestFuncCllBak
call vdiTestFuncCllBak(nrReturnValues, nrReturnValues)
call m_vdiTestFuncCllBak(1, nrReturnValues)
VdiFunctionRunner = nrReturnValues
end function VdiFunctionRunner
end module VdiFunctionRunnerMain
Because the Fortran-code need the possibility to use some functions of the C#-code to, a pass two delegates to the Fortran-code (vdiCwertCllbak, vdiIwertCllbak).
This works quite well when they are used in the MainFunction, so the interfacing works so far.
Now it is needed, that the c#-functions must be available from other functions outside of the MainFunction and even in different modules.
I tried to use functionpointers to deal with this problem, but always get the following error when calling m_vdiTestFuncCllBak. Calling vdiTestFuncCllBak works without problems.
It is the same behaviour when initializing the pointer in the function or in an external module.
The following c# code is called:
private void vdiTestFunc(ref int inputValue, ref int retValue)
{
retValue = inputValue + 1;
return;
}
The problem is, that the references of inputValue and retValue are not set when using the funtionpointer.
Does someone had the same issue before and knows a possible solution or has a link with help? I haven't found information about that in my searches.
I am using the Intel 11 compiler.
Help is very much appreciated.

A quick and dirty way would be to make a module that has a procedure pointer in it:
module callback_module
procedure(),pointer::p
end module
integer function MainFunction(XTGA, ARRAY_810, vdiCwertCllbak, vdiIwertCllbak)
!DEC$ ATTRIBUTES DLLEXPORT ::MainFunction
!DEC$ ATTRIBUTES REFERENCE :: XTGA, ARRAY_810, vdiCwertCllbak, vdiIwertCllbak
use callback_module
implicit none
external vdiCwertCllbak, vdiIwertCllbak
integer :: nrReturnValues = 1
integer :: iWertCallBackRet = 12
satzArt = '710.10' // char(0)
p=>vdiIwertCllbak
call vdiIwertCllbak(satzArt, 1, 2, iWertCallBackRet)
MainFunction= nrReturnValues
end function MainFunction
integer function tga_810(xtga,array_810)
use callback_module
character(len=256) xtga,tga,array_810(4),s, caption, inputBox
call p('710' // char(0), 1, 2, retValue)
tga_810 = 1
end function tga_810
EDIT:
The access violation might be because the pointer has no associated interface.
module callback_module
interface
subroutine callback_sub(arg1,arg2,...)
!Declare all arguments as they appear in the actual callback routine
end subroutine
end interface
procedure(callback_sub),pointer::p
end module
You'll need to correctly define the procedure arguments for the interface.
It might also be caused by having optional arguments. Does vdiIwertCllbak have optionals?

Related

How to use let with typedef signals?

I'm trying to use let-constructs instead of `define in my TB to access some signals via hierarchical paths. It's not going that great. "Normal" signals seems to work and I can access them, but typedef-signals act strange.
Here's a super simple example code that I use to trigger the error:
module dut();
// Create a type
typedef struct {
int foo;
int bar;
} ty_fooBar;
// Instantiate the type
ty_fooBar fooBar;
// Create an "alias" for fooBar
let fooBar2 = fooBar;
// Assign some values and try to access the struct members
initial begin
fooBar.foo = 3;
fooBar.bar = 7;
$display("fooBar: %p", fooBar );
$display("fooBar2: %p", fooBar2 );
$display("fooBar.fooBar: %p", fooBar.foo );
// $display("fooBar2.fooBar: %p", fooBar2.foo ); <- ERROR
end
endmodule
Simulation gives this result:
# fooBar: '{foo:3, bar:7}
# fooBar2: '{foo:3, bar:7}
# fooBar.fooBar: 3
So, fooBar should now be the same as fooBar2, ModelSim shows this with the $display command, but for some reason I can access fooBar.foo but not fooBar2.foo. I tried reading the IEEE standard but that didn't enlighten me.
What's the deal with let and typedef? Do I have some profound misunderstanding?
The let statement combines the flexibility of a `define macro with the well formed structure of function.
Like a macro. the let arguments get replaced into the body of its definition. they may be typeless.
Like a function, a let declaration is local to a scope, including a package that can be imported. References to identifiers that are not arguments are searched from the point of the declaration. And finally the problem that you are facing is that a let statement can only be called where an expression is allowed. In fact it places parenthesis around the body before substituting.
So your reference to fooBar2.foo gets expanded as (fooBar).foo which is not legal.

Using procedure in structured data type as callback for C library (GTK+3)

I'm trying to use procedures within a structured data type as callback functions for a program using GTK+3 as its toolkit in FreePascal. (The GTK+3 bindings I have were generated by the gir2pascal tool (http://wiki.freepascal.org/gir2pascal))
In the example below, I use advanced records, but I would definitely consider classes or objects if it works better/at all with them.
The problem that occurs is that when the callback procedure is called, it cannot access anything else within its own record. It seems to "forget" where it comes from.
For instance, in the example below I have the integer myRecord.myInt, that I can set and retrieve happily by calling the procedure myRecord.testProcedure. However when testProcedure is used as a C callback (when I click the button), I will receive some number (e.g. 30976), but not 7.
{$MODESWITCH ADVANCEDRECORDS}
uses gobject2, gtk3, math;
type
myRecord=record
public
myInt: Integer;
procedure testProcedure; cdecl;
end;
procedure myRecord.testProcedure; cdecl;
begin
WriteLn(myInt);
end;
var
recordInstance: myRecord;
button, win: PGtkWidget;
begin
SetExceptionMask([exDenormalized, exInvalidOp, exOverflow,
exPrecision, exUnderflow, exZeroDivide]); {this is needed for GTK not to crash}
gtk_init(#argc, #argv);
win:=gtk_window_new(GTK_WINDOW_TOPLEVEL);
recordInstance.myInt:=7;
button:=gtk_button_new;
{The following does not work. The procedure will run when the button is
clicked; it will print some number, but not the content of recordInstance.myInt}
g_signal_connect_data(button, 'clicked',
TGCallback(#recordInstance.testProcedure), nil, nil, 0);
{add button to window}
gtk_container_add(PGtkContainer(win), button);
gtk_widget_show_all(win);
{Test call to recordInstance.testProcedure to see that it outputs
'7' correctly}
recordInstance.testProcedure;
gtk_main;
end.
When I try to use Classes or Objects instead of an Advanced Record, I receive error messages of the kind
"<procedure variable type of procedure of object;CDecl>" to "<procedure variable type of procedure;CDecl>"
What ways are there of using a structured data type with a procedure to use as a C callback as in the example above (if any)?
class static methods are compatible with procedures. But they also have the disadvantage that they don't have a reference to the data of the object.
{$mode delphi}
type
myRecord=record
public
myInt: Integer;
class procedure testProcedure; cdecl;static;
end;
tproctype = procedure; cdecl;
class procedure myrecord.testProcedure; cdecl;static;
begin
end;
var x : tproctype;
y : myrecord;
begin
x:=y.testprocedure;
end.
compiles, but the usage is sterile, since if it maps to plain C, it doesn't have (implicit) OO properties.

Is there any method to know whether a member is declared random or not in a class in SV

// Current Class
class x;
rand int a;
int b; // b is nonrandom as of now
function new();
endfunction
function abc;
// if a != ref.a, where ref is reference object of class x, declared somewhere else
a.rand_mode(0);
endfunciton
// Future Possible Class
class x;
rand int a;
rand int b; // b is also a random variable now
function new();
endfunction
function abc;
// if a != ref.a, where ref is reference object of class x, declared somewhere else
a.rand_mode(0);
// if b != ref.b, where ref is reference object of class x, declared somewhere else
b.rand_mode(0);
endfunciton
So in function abc, depending upon whether a rand member value matches or doesn't match with the value of that member in reference class, that rand declared members of class x, should be active or inactive accordinly.
Purpose - I need to check if a rand variable matches with reference class value then only it should be randomized, otherwise not.
I want to generalize method abc, for all possible future variations (So I don't need to modify it, as done in the above example), and as I don't know, when a class member may become rand or nonrand member, Is there any inbuilt method to know, whether a member of a class is declared as rand or not in that class?
You could change your perspective on the problem slightly. Instead of trying to disable randomization for fields that are declared rand, why not say that when they get randomized, they should keep their value?
According to this nice post, there's a new construct in SV 2012, const'(...) that would work in this case. Unfortunately I don't think many vendors support it. Your randomize() call would look like this:
if (!rand_obj.randomize() with {
const'(a) != ref_obj.a -> a == const'(a);
})
$fatal(0, "rand error");
Let's dissect this code. const(a) will sample the value of a prior to doing any sort of randomization. If the value of a before randomization is not equal to the reference value, then we have the second part of the constraint that says a should keep its value. I've tried this code on two simulators but it wasn't supported by either (though it should be legal SV 2012 syntax). Maybe you're lucky enough to have a vendor that supports it.
You can write such constraints even for state variables, as they will still hold.
If you can't get the const syntax to work in your simulator, then the same post shows how you could work around the issue. You could store the values prior to randomization inside the object and use those in the constraint:
class some_class;
rand bit [2:0] a;
bit [2:0] b;
bit [2:0] pre_rand_a;
bit [2:0] pre_rand_b;
function void pre_randomize();
pre_rand_a = a;
pre_rand_b = b;
endfunction
endclass
When you want to randomize, you'd add the following constraints:
if (!rand_obj.randomize() with {
pre_rand_a != ref_obj.a -> a == pre_rand_a;
pre_rand_b != ref_obj.b -> b == pre_rand_b;
})
$fatal(0, "rand error");
You can find a full example on EDAPlayground.
You mention that your function that does randomization is defined outside of the object. Because of that, the pre_rand_* fields can't be local/protected, which isn't very nice. You should consider making the function a class member and pass the reference object to it, so that you can enforce proper encapsulation.
This isn't possible as SystemVerilog doesn't provide any reflection capabilities. You could probably figure this out using the VPI, but I'm not sure how complete the implementation of the VPI is for classes.
Based on what you want to do, I'd say it anyway doesn't make sense to implement such a query just to future proof your code in case some fields will one day become rand. Just as how you add the rand modifier to the field, you can also add it to the list of fields for which randomization should be disabled. Both code locations reside in the same file, so it's difficult to miss.
One certain simulator will return -1 when interrogating a state variable's rand_mode(), but this is non-standard. The LRM explicitly states that it's a compile error to call rand_mode() on non-random fields.

How to pass parameters to a Progress program using database field dynamic-based rules?

I have in my database a set of records that concentrates information about my .W's, e.g. window name, parent directory, file name, procedure type (for internal treatments purposes), used to build my main menu. With this data I'm developing a new start procedure for the ERP that I maintain and using the opportunity in order to rewrite some really outdated functions and programs and implement new functionalities. Until now, I hadn't any problems but when I started to develop the .P procedure which will check the database register of a program that was called from the menu of this new start procedure - to check if it needs to receive fixed parameters to be run and its data types - I found a problem that I can't figure out a solution.
In this table, I have stored in one of the fields the parameters needed by the program, each with his correspondent data type. The problem is on how to pass different data types to procedures based only on the stored data. I tried to pre-convert data using a CASE clause and an include to check the parameter field for correct parameter sending but the include doesn't work as I've expected.
My database field is stored as this:
Description | DATATYPE | Content
I've declared some variables and converted properly the stored data into their correct datatype vars.
DEF VAR c-param-exec AS CHAR NO-UNDO EXTENT 9 INIT ?.
DEF VAR i-param-exec AS INT NO-UNDO EXTENT 9 INIT ?.
DEF VAR de-param-exec AS DEC NO-UNDO EXTENT 9 INIT ?.
DEF VAR da-param-exec AS DATE NO-UNDO EXTENT 9 INIT ?.
DEF VAR l-param-exec AS LOG NO-UNDO EXTENT 9 INIT ?.
DEF VAR i-count AS INT NO-UNDO.
blk-count:
DO i-count = 0 TO 8:
IF TRIM(programa.parametro[i-count]) = '' THEN
LEAVE blk-count.
i-count = i-count + 1.
CASE ENTRY(2,programa.parametro[i-count],CHR(1)):
WHEN 'CHARACTER' THEN
c-param-exec[i-count] = ENTRY(3,programa.parametro[i-count],CHR(1)).
WHEN 'INTEGER' THEN
i-param-exec[i-count] = INT(ENTRY(3,programa.parametro[i-count],CHR(1))).
WHEN 'DECIMAL' THEN
de-param-exec[i-count] = DEC(ENTRY(3,programa.parametro[i-count],CHR(1))).
WHEN 'DATE' THEN
da-param-exec[i-count] = DATE(ENTRY(3,programa.parametro[i-count],CHR(1))).
WHEN 'LOGICAL' THEN
l-param-exec[i-count] = (ENTRY(3,programa.parametro[i-count],CHR(1)) = 'yes').
OTHERWISE
c-param-exec[i-count] = ENTRY(3,programa.parametro[i-count],CHR(1)).
END CASE.
END.
Then I tried to run the program using an include to pass parameters (in this example, the program have 3 INPUT parameters).
RUN VALUE(c-prog-exec) ({util\abrePrograma.i 1},
{util\abrePrograma.i 2},
{util\abrePrograma.i 3}).
Here is my abrePrograma.i
/* abrePrograma.i */
(IF ENTRY(2,programa.parametro[{1}],CHR(1)) = 'CHARACTER' THEN c-param-exec[{1}] ELSE
IF ENTRY(2,programa.parametro[{1}],CHR(1)) = 'INTEGER' THEN i-param-exec[{1}] ELSE
IF ENTRY(2,programa.parametro[{1}],CHR(1)) = 'DECIMAL' THEN de-param-exec[{1}] ELSE
IF ENTRY(2,programa.parametro[{1}],CHR(1)) = 'DATE' THEN da-param-exec[{1}] ELSE
IF ENTRY(2,programa.parametro[{1}],CHR(1)) = 'LOGICAL' THEN l-param-exec[{1}] ELSE
c-param-exec[{1}])
If I suppress the 2nd, 3rd, 4th and 5th IF's from the include or use only one data type in all IF's (e.g. only CHAR, only DATE, etc.) the program works properly and executes like a charm but I need to call some old programs, which expects different datatypes in its INPUT parameters and using the programs as described OpenEdge doesn't compile the caller, triggering the error number 223.
---------------------------
Erro (Press HELP to view stack trace)
---------------------------
** Tipos de dados imcompativeis em expressao ou atribuicao. (223)
** Nao entendi a linha 86. (196)
---------------------------
OK Ajuda
---------------------------
Can anyone help me with this ?
Thanks in advance.
Looks as if you're trying to use variable parameter definitions.
Have a look at the "create call" statement in the ABL reference.
http://documentation.progress.com/output/ua/OpenEdge_latest/index.html#page/dvref/call-object-handle.html#wwconnect_header
Sample from the documentation
DEFINE VARIABLE hCall AS HANDLE NO-UNDO.
CREATE CALL hCall.
/* Invoke hello.p non-persistently */
hCall:CALL-NAME = "hello.p".
/* Sets CALL-TYPE to the default */
hCall:CALL-TYPE = PROCEDURE-CALL-TYPE
hCall:NUM-PARAMETERS = 1.
hCall:SET-PARAMETER(1, "CHARACTER", "INPUT", "HELLO WORLD").
hCall:INVOKE.
/* Clean up */
DELETE OBJECT hCall.
The best way to get to the bottom of those kind of preprocessor related issues is to do a compile with preprocess listing followed by a syntax check on the preprocessed file. Once you know where the error is in the resulting preprocessed file you have to find out which include / define caused the code that won't compile .
In procedure editor
compile source.w preprocess source.pp.
Open source.pp in the procedure editor and do syntax check
look at original source to find include or preprocessor construct that resulted in the code that does not compile.
Okay, I am getting a little bit lost (often happens to me with lots of preprocessors) but am I missing that on the way in and out of the database fields you are storing values as characters, right? So when storing a parameter in the database you have to convert it to Char and on the way out of the database you have convert it back to its correct data-type. To not do it one way or the other would cause a type mismatch.
Also, just thinking out loud (without thinking it all the way through) wonder if using OOABL (Object Oriented ABL) depending on if you Release has it available wouldn't make it easier by defining signatures for the different datatypes and then depending on which type of input or output parameter you call it with, it will use the correct signature and correct conversion method.
Something like:
METHOD PUBLIC VOID storeParam(input cParam as char ):
dbfield = cParam.
RETURN.
END METHOD.
METHOD PUBLIC VOID storeParam(input iParam as int ):
dbfield = string(iParam).
RETURN.
END METHOD.
METHOD PUBLIC VOID storeParam(input dParam as date ):
dbfield = string(dParam).
RETURN.
END METHOD.
just a thought.

How can I specify the value of a named argument in boost.python?

i want to embed a function written in python into c++ code.
My python code is:test.py
def func(x=None, y=None, z=None):
print x,y,z
My c++ code is:
module = import("test");
namespace = module.attr("__dict__");
//then i want to know how to pass value 'y' only.
module.attr("func")("y=1") // is that right?
I'm not sure Boost.Python implements the ** dereference operator as claimed, but you can still use the Python C-API to execute the method you are intested on, as described here.
Here is a prototype of the solution:
//I'm starting from where you should change
boost::python::object callable = module.attr("func");
//Build your keyword argument dictionary using boost.python
boost::python::dict kw;
kw["x"] = 1;
kw["y"] = 3.14;
kw["z"] = "hello, world!";
//Note: This will return a **new** reference
PyObject* c_retval = PyObject_Call(callable.ptr(), NULL, kw.ptr());
//Converts a new (C) reference to a formal boost::python::object
boost::python::object retval(boost::python::handle<>(c_retval));
After you have converted the return value from PyObject_Call to a formal boost::python::object, you can either return it from your function or you can just forget it and the new reference returned by PyObject_Call will be auto-deleted.
For more information about wrapping PyObject* as boost::python::object, have a look at the Boost.Python tutorial. More precisely, at this link, end of the page.
a theoretical answer (no time to try myself :-| ):
boost::python::dict kw;
kw["y"]=1;
module.attr("func")(**kw);