pyOCCT icon indicating copy to clipboard operation
pyOCCT copied to clipboard

Methods that take a stream (ie DumpJson) don't work

Open frmdstryr opened this issue 4 years ago • 7 comments

I'm probably doing this wrong...

from OCCT.gp import *
t = gp_Trsf()

import sys
t.DumpJson(sys.stdout)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-10-653204f5a44e> in <module>
----> 1 t.DumpJson(sys.stdout)

TypeError: DumpJson(): incompatible function arguments. The following argument types are supported:
    1. (self: OCCT.gp.gp_Trsf, arg0: std::ostream) -> None
    2. (self: OCCT.gp.gp_Trsf, theOStream: std::ostream, theDepth: int) -> None

Invoked with: <OCCT.gp.gp_Trsf object at 0x7f0facf7c170>, <ipykernel.iostream.OutStream object at 0x7f0fb063bac0>

Did you forget to `#include <pybind11/stl.h>`? Or <pybind11/complex.h>,
<pybind11/functional.h>, <pybind11/chrono.h>, etc. Some automatic
conversions are optional and require extra headers to be included
when compiling your pybind11 module.

Expected Behavior

I think that should write to stdout

Current Behavior

Gives the error

Possible Solution

Does including the <pybind11/stl.h> make this work?

frmdstryr avatar May 10 '20 15:05 frmdstryr

this might be relevant? https://pybind11.readthedocs.io/en/stable/advanced/pycpp/utilities.html#capturing-standard-output-from-ostream

and

https://www.opencascade.com/doc/occt-7.4.0/refman/html/_standard___o_stream_8hxx.html

trelau avatar May 10 '20 15:05 trelau

Thanks for the links, looks like Standard_OStream is just a typedef and pybind has a pythonbuf class for this.

I have two ideas, not sure which is best (or if they'll work):

  1. Change any std::ostream functions to be lambdas that take a pyobject instead of the ostream, then wrap the object in a pythonbuf. This way would allow just using t.DumpJson(some_file_like_obj)
  2. Make Standard_OStream a py::class that creates a pythonbuf, so you have to create a Standard_OStream passing the python file like object, then pass the Standard_OStream to the function.

Any preferences? I can try to make a patch.

frmdstryr avatar May 11 '20 23:05 frmdstryr

hmm....my first thought is 2....i think at the moment Standard_OStream is just skipped in the binder https://github.com/LaughlinResearch/pyOCCT/blob/1c354c2ffb92f5c49d0a4f1c7a26a6483c8b2b9f/binder/config.txt#L118

so, seems like if we just bind Standard_OStream...then we just create one in python and existing functions just work? and it follows the OCCT api. otherwise, #1 seems like a case that will require special logic in the binding generator to handle that type and writing the lambdas. which, we could do, but seems like 2 is worth a shot?

trelau avatar May 11 '20 23:05 trelau

In some cases these methods can write to a file so as a workaround I've created a temporary file, used OCCT to write to the file, and then read the file

cfriedland5 avatar Jul 15 '20 13:07 cfriedland5

Did anything happen related to this issue since it was raised? I get similar issues.

ThomasAuzinger avatar Mar 26 '21 11:03 ThomasAuzinger

Seems that this gist provides a smooth and easy to integrate solution to this problem via custom type casting.

russelmann avatar May 04 '21 12:05 russelmann

I can confirm that the gist was the way to go, though for me it required some modifications: https://github.com/CadQuery/OCP/blob/master/pystreambuf.h

adam-urbanczyk avatar Jul 22 '21 16:07 adam-urbanczyk