Edit
Same behavior without FORTRAN and undocumented part. What can be wrong in this case? LibraryFunction below is supposed to be just an identity function.
(* wrapper *)
wra = "
#include \"WolframLibrary.h\"
#include \"WolframCompileLibrary.h\"
DLLEXPORT mint WolframLibrary_getVersion(){
return WolframLibraryVersion ;
}
DLLEXPORT int WolframLibrary_initialize(WolframLibraryData libData){
return 0 ;
}
EXTERN_C DLLEXPORT int plus(WolframLibraryData libData, mint Argc, MArgument *Args, MArgument Res){
MTensor A ;
mint I, J ;
A = MArgument_getMTensor(Args[0]) ;
MArgument_setMTensor(Res,A) ;
return LIBRARY_NO_ERROR ;
}
" ;
(* export wrapper *)
SetDirectory[NotebookDirectory[]] ;
Export["wrapper.cc",wra,"String"] ;
(* create library *)
Needs["CCompilerDriver`"]
CreateLibrary[
{"wrapper.cc"},
"plus",
Rule["TargetDirectory",NotebookDirectory[]],
Rule["CleanIntermediate",True],
Rule["CompileOptions"," "],
Rule["Debug",False]
] ;
(* load library *)
LIB = LibraryFunctionLoad[StringJoin[NotebookDirectory[],"plus"],"plus",List[List[Real,1]],List[Real,1]]
(* version with check for arg *)
FUN[VAR_] := LIB[VAR] /; Apply[And,Map[NumberQ,VAR]] ;
Repeated execution of this cell results in kernel crash
OUT = NestList[LIB,INI,100] ;
Original post
For some reason using Nestlist with LibraryFunction can lead to kernel crash. It looks like something non-numerical is passed to LibraryFunction. There is no problem if the argument is checked, but my argument can be a long list and the number of NestList iterations can be large too. Is there a better workaround in this case?
$Version
(* 12.0.0 for Linux x86 (64-bit) (April 7, 2019) *)
(* wrapper *)
wra = "
#include \"WolframLibrary.h\"
#include \"WolframCompileLibrary.h\"
DLLEXPORT mint WolframLibrary_getVersion(){
return WolframLibraryVersion ;
}
DLLEXPORT int WolframLibrary_initialize(WolframLibraryData libData){
return 0 ;
}
extern \"C\" {
void plus_(mreal a[]) ;
}
EXTERN_C DLLEXPORT int plus(WolframLibraryData libData, mint Argc, MArgument *Args, MArgument Res){
MTensor A ;
A = MArgument_getMTensor(Args[0]) ;
plus_(MTensor_getRealDataMacro(A)) ;
MArgument_setMTensor(Res,A) ;
return LIBRARY_NO_ERROR ;
}
" ;
(* program *)
pro = "
pure subroutine plus(x)
implicit none
real(8),intent(inout), dimension(10) :: x
x = x + 1.0_8
end subroutine plus
" ;
(* export wrapper & program *)
SetDirectory[NotebookDirectory[]] ;
Export["wrapper.cc",wra,"String"] ;
Export["plus.f90",pro,"String"] ;
(* compile program *)
Run["gfortran -c plus.f90 "]
(* create library *)
Needs["CCompilerDriver`"]
CreateLibrary[
{"wrapper.cc","plus.o"},
"plus",
Rule["TargetDirectory",NotebookDirectory[]],
Rule["CleanIntermediate",True],
Rule["CompileOptions"," "],
Rule["Debug",False]
] ;
(* load library *)
LIB = LibraryFunctionLoad[StringJoin[NotebookDirectory[],"plus"],"plus",List[List[Real,1]],List[Real,1]]
(* version with check for arg *)
FUN[VAR_] := LIB[VAR] /; Apply[And,Map[NumberQ,VAR]] ;
Works fine
INI = ConstantArray[0.,10] ;
FUN[INI]
LIB[INI]
Works fine
OUT = NestList[FUN,INI,100] ;
Repeated execution of this cell results in kernel crash
OUT = NestList[LIB,INI,100] ;
Rule[1,2]andList[1,2]become very hard to follow once they're nested. Use1 -> 2and{1, 2}. – Szabolcs Aug 17 '19 at 10:48MTensor_getRealDataMacroinstead of the documented APIlibData->MTensor_getRealData. Is there any reason you want to do this? – Szabolcs Aug 17 '19 at 10:55MTensor_getRealDataMacro, just seen it here, I'll test the code with automatic fortran array size, not sure fixed size is the problem – I.M. Aug 17 '19 at 12:14