I am using Python4Delphi to embed Python in a Delphi program. Versions: Python 2.6.4, Delphi 2009, Windows XP.
The Delphi program crashes with EInvalidOp when importing json. I tracked it to the line
NaN, PosInf, NegInf = float('nan'), float('inf'), float('-inf')
in json.decoder.
Sure enough, the command float('nan') raises an EInvalidOp when run inside Python embedded in the Delphi program. When executed in the command line Python (same installation) it simply returns nan.
Any idea what is the difference between the Python standard startup and that of the embedded one that may result in such an error?
This is most likely that Python uses a different 8087 control word (CW) setting than Delphi.
Try this kind of code:
var
OldControlWord: Word;
begin
OldControlWord := Get8087CW();
Set8087CW($133F);
try
// perform your Python code here
finally
Set8087CW(OldControlWord);
end;
end;
See my blog article on the 8087 CW in Delphi for a more detailed explanation of the $133F value.
It needs the JCL for the T8087Precision type (which is in the Jcl8087 unit).
--jeroen
I use the following:
$1332 is the delphi default.
$1232 is the value to deal with Python Issue 9980.
procedure MaskFPUExceptions(ExceptionsMasked : boolean);
begin
// if ExceptionsMasked then
// Set8087CW($1332 or $3F)
// else
// Set8087CW($1332);
if ExceptionsMasked then
Set8087CW($1232 or $3F)
else
Set8087CW($1232);
end;
Related
I have an issue in executing the Calculate field command in Python (ArcPy). I couldn't find any related resources or helpful descriptions regarding this. I hope somebody could help me with this.
inFeatures = r"H:\Python Projects\PycharmProjects\ArcPy\Test_Output\Trial_out.gdb\Trail_Data_A.shp"
arcpy.CalculateField_management(inFeatures, 'ObjArt_Ken', '!AttArt_Ken!'.split('_')[0])
arcpy.CalculateField_management(inFeatures, 'Wert', '!AttArt_Ken!'.split('_')[-1])
The error i am getting when I run the command is
arcgisscripting.ExecuteError: Error during execution. Parameters are invalid.
ERROR 000989: The CalculateField tool cannot use VB expressions for services.
Error while executing (CalculateField).
I am using ArcGIS Pro 2.8 and Python 2.7
I found a working output for the above mentioned question
inTable = r'H:\Python Projects\PycharmProjects\ArcPy\Test_Output\Trial_out.gdb\Trail_Data_A.shp'
func_1 = "'!AttArt_Ken!'.split('_')[0]"
field_1 = "ObjArt_Ken"
func_2 = "'!AttArt_Ken!'.split('_')[1]"
field_2 = "Wert"
arcpy.AddField_management(inTable, field_1, "TEXT".encode('utf-8'))
arcpy.CalculateField_management(inTable, field_1, func_1, "PYTHON_9.3")
arcpy.AddField_management(inTable, field_2, "TEXT".encode('utf-8'))
arcpy.CalculateField_management(inTable, field_2, func_2, "PYTHON_9.3")
But a problem still exists such that the output (After split function) is like
|ObjArt_Ken|Wert|
|:---|:---|
|u"31001|1001"|
I still couldn't figure out a way to remove the unicode or the '"' symbol from the desired output
Since I can't comment yet, I will have to use an Answer to make several comments
You need to clarify, "I am using ArcGIS Pro 2.8 and Python 2.7." ArcGIS Pro has always come bundled with Python 3.x, and ArcGIS Desktop/ArcMap has always been bundled with Python 2.x. It is not possible to use ArcGIS Pro and Python 2.7. Given the error message, it appears you are running some version of ArcMap and Python 2.7.
The original error message, as you seemed to have figured out, was telling you exactly what wasn't working originally. Since you didn't pass expression_type to Calculate Field and you are using some version of ArcMap that defaults to VB, the function was interpreting your expression as VB code and erring because "CalculateField tool cannot use VB expressions for services."
Looking at the newer code, I am not sure why you are encoding field_type. Although I tested it and it works, it is unnecessary and confusing to someone looking at the code.
Unless you provide some samples of what the AttArt_Ken field contains, people can't really comment on the output you are seeing.
I want to use the Delphi 4 Python components from here https://github.com/pyscripter/python4delphi
but I don't want to drop the components on a form, I want everything in code , my code goes like this :
var
PythonEngine_netA: TPythonEngine;
PythonInputOutput_netA: TPythonInputOutput;
begin
PythonEngine_netA := TPythonEngine.Create(Self);
PythonInputOutput_netA := TPythonInputOutput.Create(Self);
try
/// configure the components
PythonEngine_netA.DllName:='python39.dll';
PythonEngine_netA.IO := PythonInputOutput_netA;
PythonEngine_netA.UseLastKnownVersion := True;
PythonInputOutput_netA.OnSendUniData := PythonInputOutput_SendUniData;
PythonInputOutput_netA.UnicodeIO := True;
PythonInputOutput_netA.RawOutput := True;
/// execute the script
PythonEngine_netA.ExecString(UTF8Encode(mmo_pythoncode.text));
finally
PythonEngine_netA.free;
PythonInputOutput_netA.free;
end;
execution of this code fails, error msg : "Python is not properly initialized",
what did I miss to use this code ?
One quick look at PythonEngine.pas (or even better: always search all files for the error message to find out where and why an error is returned) tells me you missed calling PythonEngine_netA.Initialize().
Also note that /Demos describes:
Demo34 Dynamically creating, destroying and recreating PythonEngine. Uses PythonVersions
So please have a look at /Demos/Demo34/Unit1.pas how it is done there with (almost) no components. Or run the whole project in general, preferably in debug mode single stepping thru it be aware which method does what.
You just forgot to load the Dll:
PythonEngine_netA.UseLastKnownVersion:= True;
//PythonEngine_netA.opendll(PYDLL)
PythonEngine_netA.LoadDll;
PythonEngine_netA.IO:= PythonInputOutput_netA;
I want to use functions in dll's via ctype. I can call the function without errors and even the error code of the function is 0 meanig function successfuly finished. But when I try to acces the result variable ist is empty.
I have been implemented the lookup in free pascal severeal years ago and would transfer it to python right now. The interface allow to access via cdel convention and I tied to reimplement in python 3.7.4 with ctypes now
The last working Pascal Prototype have been:
PROCEDURE pGetCallInfo(DriveInfo: pointer; ACall: pointer; AInfo: pointer;
var AErrorCode: SmallInt); pascal; external 'raccd32a.dll';
My best version in python have been the following:
from ctypes import *
callBookDLL = CDLL('raccd32a')
AInfo = create_string_buffer(400)
err = callBookDLL.cGetCallInfo("self.txt_CallBookPath.text()","DG1ATN",AInfo)
The result ist:
err
0
AInfo.value
b''
AInfo should contain a max. 400 char long stringbuffer with an result containing Name, Adress and so on.
As I have a second library I have to acces same way I search for my fault but I was not able to find it. I think my problem is the work with pointer and the type conversion.
I checked teh ctypes howto allready but I can noht solve this trouble.
Thanks a lot so far ...
Check [Python 3.Docs]: ctypes - A foreign function library for Python. It contains (almost) every piece of info that you need.
There are a number of problems:
ctypes doesn't support pascal calling convention, only cdecl and stdcall (applies to 32bit only). That means (after reading the manual) that you shouldn't use the p* functions, but the c* (or s*)
You didn't specify argtypes (and restype) for your function. This results in UB. Some effects of this:
[SO]: Python ctypes cdll.LoadLibrary, instantiate an object, execute its method, private variable address truncated (#CristiFati's answer)
[SO]: python ctypes issue on different OSes (#CristiFati's answer)
It is a procedure (a function that returns void). Anyway this is a minor one
Here's some sample code (of course it's blind, as I didn't test it):
#!/usr/bin/env python3
import sys
import ctypes
dll = ctypes.CDLL("raccd32a.dll")
cGetCallInfo = dll.cGetCallInfo
cGetCallInfo.argtypes = [ctypes.c_char_p, ctypes.c_char_p, ctypes.c_char_p, ctypes.POINTER(ctypes.c_short)]
cGetCallInfo.restype = None
ADriveInfo = self.txt_CallBookPath.text().encode()
#ADriveInfo = b"C:\\callbook2019\\" # Notice the double bkslashes
ACall = b"DG1ATN"
AInfo = ctypes.create_string_buffer(400)
result = ctypes.c_short(0)
cGetCallInfo(ADriveInfo, ACall, AInfo, ctypes.byref(result))
#EDIT0:
From the beginning, I wanted yo say that the 1st argument passed to the function doesn't make much sense. Then, there are problems regarding the 2nd one as well. According to the manual ([AMT-I]: TECHNICAL INFORMATION about RACCD32a.DLL (emphasis is mine)):
ADriveInfo, ACall and AInfo are pointers to zero-terminated strings. These
strings has to exist at the moment of calling xGetCallInfo. The calling
program is responsible for creating them. AInfo must be long enough to
comfort xGetCallInfo (at least 400 characters).
Note: "Length of AInfo" refers to the length of the string AInfo points at.
ADriveInfo and ACall are treated in the same manner for short.
In ADriveInfo the procedure expects the path to the CD ROM drive. Use
"G:\"
if "G:" designates the CD ROM drive with the callbook CD ROM.
Keep in mind that this information is a *must* and the calling program
has to know it.
Note: If the active directory on drive G: is not the root, ADriveInfo = "G:"
will lead to an error 3. So always use "G:\".
The calling program has to ensure that the length of ADriveInfo does not
exceed 80 characters.
ACall contains the call you are looking for, all letters in lower case,
no additional spaces etc. The calling program has to ensure that ACall is
not longer than 15 characters. However, there is no call longer than 6
characters in the database.
I have a working python 2.7 program that calls a DLL. I am trying to port the script to python 3.2. The DLL call seems to work (i.e. there is no error upon calling) but the returned data does not make sense.
Just in case it could be useful:
- The call takes three arguments: two int (input) and a pointer to a ushort array (output).
I have tried using both python and numpy arrays without success.
Can anyone enumerate the differences between Python 2.7 and 3.2 respecting ctypes?
Thanks in advance
EDIT
Here is some example code. The DLL is propietary so I do not have the code. But I do have the C header:
void example (int width, int height, unsigned short* pointer)
The python code is:
width, height = 40, 100
imagearray = np.zeros((width,height), dtype=np.dtype(np.ushort))
image = np.ascontiguousarray(imagearray)
ptrimage = image.ctypes.data_as(ct.POINTER(ct.c_ushort))
DLL.example(width, height, ptrimage)
This works in python 2.7 but not in 3.2.
EDIT 2
If the changes in ctypes are only those pointed out by Cedric, it does not make sense that python 3.2 will not work. So looking again at the code, I have found that there is a preparation function called before the function that I am mentioning. The signature is:
void prepare(char *table)
In python, I am calling by:
table = str(aNumber)
DLL.prepare(table)
Is it possible that the problem is due to the change in the Python string handling?
In Python 2.7, strings are byte-strings by default. In Python 3.x, they are unicode by default. Try explicitly making your string a byte string using .encode('ascii') before handing it to DLL.prepare.
Edit:
#another way of saying table=str(aNumber).encode('ascii')
table = bytes(str(aNumber), 'ascii')
DLL.prepare(table)
In our case, we had code looking like:
addr = clib.some_function()
data = some_struct.from_address(addr)
This worked in python 2 but not in 3. The reason turned out not to be any difference in ctypes, but rather a change in memory layout that unmasked a bug in the code above. In python 2, the address returned was always (by chance) small enough to fit inside a C int (32-bit), which is the default return type for all ctypes function calls. In python 3, the addresses were almost always too large, which caused the pointer address to become corrupted as it was coerced to int.
The solution is to set the function restype to a 64-bit integer type to ensure that it can accommodate the whole address, like:
clib.some_function.restype = c_longlong
or:
clib.some_function.restype = POINTER(some_struct)
According to the python documentation, the only changes between 2.7 and 3.2 is here
A new type, ctypes.c_ssize_t represents the C ssize_t datatype.
In 2.7, there was some other modifications introduced :
The ctypes module now always converts None to a C NULL pointer for
arguments declared as pointers. (Changed by Thomas Heller; issue
4606.) The underlying libffi library has been updated to version
3.0.9, containing various fixes for different platforms. (Updated by
Matthias Klose; issue 8142.)
I'm not sure it will explain the cause of your problem...
Evaluating a sample piece of shellcode using a C program is not complicated. It would involve storing the shellcode in a character array, creating a function pointer, typecasting the pointer and making it point to the array and calling the function(pointer).
This is how it works, assuming you can execute the memory at nastycode[]:
/* left harmless. Insert your own working example at your peril */
char nastycode[] = "\x00\x00\x00...";
void (*execute_ptr) (void);
execute_ptr = (void *)nastycode; /* point pointer at nasty code */
execute_ptr(); /* execute it */
Is there any way I could do the same using Python code? Or does the fact that Python code translates to bytecode render such an endeavour impossible?
The only way this could be done is if you rely on a C library. Buffer overflows can be introduced into python from its library bindings. For your purposes you could write your own simple python library in c and implement something like example3.c in Aleph One's Smashing the Stack for Fun and Profit. As Avilo pointed out you will have to worry about NX zones, however any region of memory can be made executable again and this is platform specific. Also GCC uses stack canaries by default. Although this can be avoided by just overwriting the return address with an address passed to the function, which would leave the cannery intact. ASLR is a very good security system that can be difficult to bypass, but if you are passing in the known address to your shell code then ASLR shouldn't be a problem.
This is what you are looking for ;)
http://libemu.carnivore.it/
Since you where looking for python:
https://github.com/buffer/pylibemu
Its possible in python... you can do your own binding to C using ctypes or simply use something like distorm
http://code.google.com/p/distorm/wiki/Python
you also might want to check out how dionaea does it. Its a honeypot but it'll test shellcode and output the results.
http://dionaea.carnivore.it/