@caseih, that makes senseIt might have something to do with setting the __name__ variable for the python script.
python experiment
Re: python experiment
Re: python experiment
Maybe use a pipe?srvaldez wrote:the one hairy detail is: how to exchange data between the python script and FB, sure you could write it to a file and then read it, but that's not very efficient.
Re: python experiment
Srvaldez.
Test 64 bits.
When I use
#Define PyRun_AnyFile(fp, name_) PyRun_AnyFileExFlags(fp, name_, 0, NULL)
i.e.
dim as file ptr fp=fopen("time.py","rb")
PyRun_AnyFile(fp,"time.py")
I get the interpreter command line >>>
Test 64 bits.
When I use
#Define PyRun_AnyFile(fp, name_) PyRun_AnyFileExFlags(fp, name_, 0, NULL)
i.e.
dim as file ptr fp=fopen("time.py","rb")
PyRun_AnyFile(fp,"time.py")
I get the interpreter command line >>>
Re: python experiment
@dodicat
the example I posted is flawed, it does not check whether fp contains a valid pointer, I suspect that in your test fopen("time.py","rb") failed to open the file, perhaps if you use the full path it will work.
the example I posted is flawed, it does not check whether fp contains a valid pointer, I suspect that in your test fopen("time.py","rb") failed to open the file, perhaps if you use the full path it will work.
Re: python experiment
@jj2007
I did a fair amount of web searching and pipes were among the hits, it's a pity that there's no simple and efficient way to exchange data.
I did a fair amount of web searching and pipes were among the hits, it's a pity that there's no simple and efficient way to exchange data.
Re: python experiment
@dodicat
PyRun_AnyFile will also accept stdin as a valid file, my guess is that if fp=0 then the default is stdin and therefore you are greeted with the python prompt.
PyRun_AnyFile will also accept stdin as a valid file, my guess is that if fp=0 then the default is stdin and therefore you are greeted with the python prompt.
Re: python experiment
I'm no Python expert, so it would cost me a steep learning curve, but memory-mapped files are also an option. Under Windows, you can also share data via a DLL.srvaldez wrote:I did a fair amount of web searching and pipes were among the hits, it's a pity that there's no simple and efficient way to exchange data.
Re: python experiment
thanks for the suggestion, but this is more than I am willing to invest, after all, it's just a cursory look at embedding python in FB.
Re: python experiment
There are several methods. You can create a Python object from FB, such as a Python list, and then insert data into that list. You could also cast your FB data structure as a zstring ptr and then pass to a Python function as a "bytes" object, and then in Python use the ctypes or struct module to access the data out of this byte array. The final alternative is to create a Python function using the C API and have that function pass data between FB and Python. See https://stackoverflow.com/questions/139 ... hon-script. Not exactly super easy, but not that hard either. Lua is probably easier.srvaldez wrote:@jj2007
I did a fair amount of web searching and pipes were among the hits, it's a pity that there's no simple and efficient way to exchange data.
Re: python experiment
@caseih
perhaps another time, somehow I lack the motivation, speaking of Lua, I came across Lunatic Python
perhaps another time, somehow I lack the motivation, speaking of Lua, I came across Lunatic Python
Re: python experiment
Trivial with files, not much success yet with pipes or other methods suggested by caseih.
There's always tomorrow.
There's always tomorrow.
Code: Select all
#inclib "python37"
#include "file.bi"
'=====================================
Declare Sub Pyinit Cdecl Alias "Py_Initialize"()
Declare Function runstring Cdecl Alias "PyRun_SimpleString"(Byval s As zstring Ptr) As Integer
Declare Sub setname Cdecl Alias "Py_SetProgramName"(As String)
Declare Function PyMain Cdecl Alias "Py_Main"(As Long=0,Byref As zstring Ptr =0) As Long
Declare Sub Pyfinish Cdecl Alias "Py_Finalize"()
Sub runfile(filename As String)
runstring("exec(open('"+filename+"').read())")
End Sub
Function loadfile(file As String) As String
If Fileexists(file)=0 Then Print file;" not found":Sleep:End
Var f=Freefile
Open file For Binary Access Read As #f
Dim As String text
If Lof(f) > 0 Then
text = String(Lof(f), 0)
Get #f, , text
End If
Close #f
Return text
End Function
Function max(a() As Double) As Double
Dim As String s="L=["
For n As Long=Lbound(a) To Ubound(a)
s+=Str(a(n))+","
Next
s=Rtrim(s,",")
s+="]"
runstring s
runstring "print('data = ',L)"
runstring "x=max(L)"
runstring "fp=open('out.txt','w')"
runstring "fp.write(str(x))"
runstring "fp.close()"
max=Val(loadfile("out.txt"))
Kill "out.txt"
if fileexists("out.txt") then print "deletion failed"
End Function
Dim As Double z(1 To ...)={4.8,-6.9,3.2,56,-8,34.7,56.1,0,-67,72.6,78.0003,34.3,-9}
pyinit
Print max(z());" is the maximum"
pyfinish
Sleep
Re: python experiment
The SOF article speaks only about passing data to Python. You might look at Sending WM_COPYDATA in Python with ctypes. Instead of using FindWindow, pass the FB window handle to Python.caseih wrote:The final alternative is to create a Python function using the C API and have that function pass data between FB and Python. See https://stackoverflow.com/questions/139 ... hon-script.
Re: python experiment
The same mechanisms transfer data two ways. Once the list object is created in FB, the Python code can add objects to it, and back in FB you can grab them out of the list and unpack their data.jj2007 wrote:The SOF article speaks only about passing data to Python. You might look at Sending WM_COPYDATA in Python with ctypes. Instead of using FindWindow, pass the FB window handle to Python.caseih wrote:The final alternative is to create a Python function using the C API and have that function pass data between FB and Python. See https://stackoverflow.com/questions/139 ... hon-script.
Also you can call Python functions from the API, and unpack the result from the resulting PyObject. Also you can create a wrapper that python can use to call your FB functions. Really it's all there in the API. Been years since I last did it, but I have done it before in C. There are some tutorials (written in C of course) for using the Python C API on the main web site.
Re: python experiment
In my libpruio project I auto-create a Python ctypes wrapper from fb source code by fbdoc and the py_ctypes plugin. See file src/python/CMakeLists.txt for details.caseih wrote:Also you can create a wrapper that python can use to call your FB functions. Really it's all there in the API. Been years since I last did it, but I have done it before in C. There are some tutorials (written in C of course) for using the Python C API on the main web site.
Regards
Re: python experiment
ctypes looks like a system install, I can find no simple download to add to the working folder.
Python is very slow compared to fb .
I expected this of course due to python's integer data type.
64 bit python nevertheless seems much faster than 32 bit python for this example:
A nice touch is that you can optimise -gen gcc to -O(infinity) and it won't make a hoot of a difference.
Python is very slow compared to fb .
I expected this of course due to python's integer data type.
64 bit python nevertheless seems much faster than 32 bit python for this example:
A nice touch is that you can optimise -gen gcc to -O(infinity) and it won't make a hoot of a difference.
Code: Select all
#inclib "python37"
'=====================================
Declare Sub Pyinit Cdecl Alias "Py_Initialize"()
Declare Function runstring Cdecl Alias "PyRun_SimpleString"(Byval s As zstring Ptr) As Integer
Declare Sub setname Cdecl Alias "Py_SetProgramName"(As String)
Declare Function PyMain Cdecl Alias "Py_Main"(As Long=0,Byref As zstring Ptr =0) As Long
Declare Sub Pyfinish Cdecl Alias "Py_Finalize"()
Sub runfile(filename As String)
runstring("exec(open('"+filename+"').read())")
End Sub
Sub runfileex(filename As String,flag As boolean=true)
runstring( "fp=open('"+filename+"','r')")
runstring("codestring=fp.read()")
If flag Then runstring("print(codestring)")
runstring("exec(codestring)")
End Sub
Sub savefile(filename As String,file_content As String)
Dim As Integer n
n=Freefile
If Open (filename For Binary Access Write As #n)=0 Then
Put #n,,file_content
Close
Else
Print "Unable to save " + filename
End If
End Sub
'==========================================
Function isprime(n As Ulongint) As long
If (n=2) Or (n=3) Then Return -1
If n Mod 2 = 0 Then Return 0
If n Mod 3 = 0 Then Return 0
Dim As Ulongint limit=Sqr(N)+1
For I As Ulongint = 6 To limit Step 6
If n Mod (i-1) = 0 Then Return 0
If n Mod (i+1) = 0 Then Return 0
Next I
Return -1
End Function
Sub CreatePyIsprime
Dim As String s
s="import math"+Chr(10)
s+="def isprime(n):"+Chr(10)
s+=" if ((n==2) or (n==3)):"+Chr(10)
s+=" return -1"+Chr(10)
s+=" if (n % 2 == 0):"+Chr(10)
s+=" return 0"+Chr(10)
s+=" if ((n % 3) == 0) :"+Chr(10)
s+=" return 0"+Chr(10)
s+=" limit=math.sqrt(n)+1"+Chr(10)
s+=" for i in range(6,int(limit),6):"+Chr(10)
s+=" if (n % (i-1) == 0):"+Chr(10)
s+=" return 0"+Chr(10)
s+=" if (n % (i+1) == 0):"+Chr(10)
s+=" return 0"+Chr(10)
s+=" return -1"+Chr(10)
savefile("Pyisprime.py",s)
End Sub
function test as long
CreatePyIsPrime
Print "Primes in range 100000000000000 to 100000000000300"
Print "Python"
Dim As String script
script ="import Pyisprime"+Chr(10)
script+="for n in range(100000000000000,100000000000300):"+Chr(10)
script+=" if(Pyisprime.isprime(n)==-1):"+Chr(10)
script+=" print(n)"
Dim As Double t=Timer
setname "Compare speeds"
Pyinit
runstring(script)
Pyfinish
Print "time ";int((Timer-t)*1000);" milliseconds"
Print
Print "FB"
t=Timer
For n As Longint=100000000000000 To 100000000000300
If isprime(n) Then Print str(n)
Next
Print "time ";int((Timer-t)*1000);;" milliseconds"
print
print "Press a key to end . . ."
sleep
return 0
end function
end test