Jump to content
Sign in to follow this  
shineworld

get back a Image() object created from Python

Recommended Posts

Hi all,
 

I'm using DelphiVCL + PyScripter to develop a Python windows application.I've created and "pyd" extension module in which perform some critical time operations or add support functions missing in DelphiVCL.

- In python script I create an Image
- now I would like to send a bytes array to cnc_vision_ext module (made with Delphi):

import delphivcl
import cnc_vision_ext as ext

....
my_Image = delphivcl.Image(Form1)
ext.update_image_from_bytes(my_image, 1024, 768, 3)

Now in the wrapper CncVisionUpdateImageFromBytesArray_Wrapper I need to extract the TImage instance contained in PPyObject of args.
I was not able to find the right way....

 

{ generic functions wrappers }

function CncVisionUpdateImageFromBytesArray_Wrapper(pself, args: PPyObject): PPyObject; cdecl;
var
  Image: TImage;
  Width: Integer;
  Height: Integer;
  Channels: Integer;
  Bytes: TByteArray;
  ImagePyObj: PPyObject;
begin
  with GetPythonEngine do
  begin
    if PyArg_ParseTuple(args, 'Oiii:update_image_from_bytes', @ImagePyObj, @Width, @Height, @Channels) <> 0 then
    begin
      // ??? HOW TO GET BACK wrapped TImage from Image() object created with my_image = delphivcl.Image(owner) ???
      Image := TImage((PythonToDelphi(ImagePyObj) as TPyDelphiObject).DelphiObject);
      Result := PyUnicodeFromString
      (
        Format('%s %d %d %d', [Image.Name, Width, Height, Channels])
      );
    end
    else
      Result := nil;
  end;
end;
{ TPyExtensionManager }

procedure TPyExtensionManager.WrapperInitializationEvent(Sender: TObject);
begin
  FWrapper.RegisterDelphiWrapper(TPyCncVisionVideoCapturePxc_Wrapper);
  FWrapper.RegisterFunction
  (
    PAnsiChar('update_image_from_bytes'),
    CncVisionUpdateImageFromBytesArray_Wrapper,
    PAnsiChar('update delphivcl Image object from bytes array with width, height & channels')
  );
  FWrapper.RegisterFunction
  (
    PAnsiChar('get_usb_camera_device_list'),
    CncVisionGetUSBCameraDeviceList_Wrapper,
    PAnsiChar('get list of available usb camera devices')
  );
end;


Thanks in advance for the suggestions....
Best Regards
Silverio

Share this post


Link to post

Seems this works but is hard to say OK, at moment, for me:

 

{
        A                    B                                                      C
        +-------------------++------------------------------------------------------+
        | PyObject header   ||             TPyObject class                          |
        +----------+--------++-----------------+------------+----------+------------+
        |ob_refcnt |ob_type ||hidden Class Ptr |PythonType  |IsSubType |PythonAlloc |
        |integer   |pointer ||pointer          |TPythonType |Boolean   |Boolean     |
        |4 bytes   |4 bytes ||4 bytes          |4 bytes     |1 byte    |1 byte      |
        +----------+--------++-----------------+------------+----------+------------+

        ^                    ^
        |                    |
        ptr returned         ptr returned by Adjust
        by GetSelf

        - a Python object must start at A.
        - a Delphi class class must start at B
        - TPyObject.InstanceSize will return C-B
        - Sizeof(TPyObject) will return C-B
        - The total memory allocated for a TPyObject instance will be C-A,
          even if its InstanceSize is C-B.
        - When turning a Python object pointer into a Delphi instance pointer, PythonToDelphi
          will offset the pointer from A to B.
        - When turning a Delphi instance into a Python object pointer, GetSelf will offset
          Self from B to A.
        - Properties ob_refcnt and ob_type will call GetSelf to access their data.
}
function CncVisionUpdateImageFromBytesArray_Wrapper(pself, args: PPyObject): PPyObject; cdecl;
var
  Image: TImage;
  Width: Integer;
  Height: Integer;
  Channels: Integer;
  Bytes: TByteArray;
  ImagePyObj: PPyObject;
begin
  with GetPythonEngine do
  begin
    if PyArg_ParseTuple(args, 'Oiii:update_image_from_bytes', @ImagePyObj, @Width, @Height, @Channels) <> 0 then
    begin
      Image := TPyDelphiImage(TPyObject(PAnsiChar(ImagePyObj)+Sizeof(PyObject))).DelphiObject;
      Result := PyUnicodeFromString
      (
        Format('%s %d %d %d', [Image.Name, Width, Height, Channels])
      );
    end
    else
      Result := nil;
  end;
end;

 

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×