Is there a way to allow for a win32com object to be modified by a COM object method? - python

In native visual basic within Excel, the expected behavior is
Dim AvayaReport As Object
Dim AvayaServer As Object
...
...
Set ReportInfo = AvayaServer.Reports.Reports("<Report Name>")
AvayaServer.Reports.CreateReport ReportInfo, AvayaReport
After the last line, the CreateReport method mutates AvayaReport to be a report object in this library. However, when I replicate this code within Python, AvayaReport does not get mutated.
import win32com.client
...
AvayaReport = win32com.client.dispatch("ACSREP.cvsReport")
...
ReportInfo = AvayaServer.Reports.Reports(r'<Report Name>")
AvayaServer.Reports.CreateReport(ReportInfo, AvayaReport)
I have tried to compare the behavior between the two environments and with the exception of this issue, the surrounding code is working as intended. However, this COM object has this weird implementation where it requires an empty object to be passed into it's arguments and it changes that object to reflect the created report, but I cannot figure out a way to make this work within Python.
Within VBA, the CreateReport definition is as follows:
Function CreateReport(oRepInfo, oReport, [sTimeZone as String = "default"]) As Boolean
Member of ACSTLG.cvsCatalog

Related

python win32com excel >> ws.cells(1, 1).value does not work

i have used win32com.client to to something with excel.
so far, ".cells(1, 1).value" method succesfully read the value in row1, column1.
but from now, that code doesn't work.
it occurs error >>
'<win32com.gen_py.Microsoft Excel 16.0 Object Library._Worksheet instance at 0x2284591006720>' object has no attribute 'cells'
what is a problem?
xlsApp = win32com.client.GetActiveObject("Excel.Application")
wb = xlsApp.Workbooks(wb_name)
ws = wb.Worksheets(ws_name)
test = ws.cells(1, 1).value
print(test)
The method name is Cells() with an uppercase ‘C’ is the simple answer.
It is fair to ask: “If cells() worked before, why doesn’t it work now?”. IMHO it is a failing of win32com.
win32com will, if asked, generate a wrapper for COM objects (using a package called gen_py which creates a Python file for each object). If such a wrapper exists win32com will use it by default. This wrapper is case-sensitive. This is “early binding”.
If there is not a wrapper then calls like GetActiveObject() and Dispatch() will use “late binding” where win32com will try and call whatever method you want on the object (whether the method exists or not). The package takes whatever method you ask for and tries to get the ID of that function from the COM object via IDispatch.GetIdsOfNames(). Crucially, this lookup is case-INsensitive: using cells(),Cells() or even cElLs() will all work.
And this is the problem. The generated wrappers are stored in the user’s directory. Your code might have been happily using late-binding and cells(), but another programme may have created the wrapper at a later date. Now your code will see this wrapper and switch to early-binding and now cells() no longer works: you need to use Cells().
So, when using win32com it is always worth finding out the exact function name from the reference, eg from here

How to get the source code for property in python

I want to programmatically get the source code for a given class property (e.g., pandas.DataFrame.iloc). I tried using inspect.findsource(), which works fine for classes and functions. However, it doesn't work for properties.
import pandas
import inspect
type(pandas.DataFrame) # type
inspect.findsource(pandas.DataFrame) # works ok
type(pandas.DataFrame.apply) # function
inspect.findsource(pandas.DataFrame.apply) # works ok
type(pandas.DataFrame.iloc) # property
inspect.findsource(pandas.DataFrame.iloc) # throws exception
TypeError: module, class, method, function, traceback, frame, or code object was expected, got property
Why inspect cannot find source for property? How can I programmatically get the source code (or source file path) for a given property?

checking whether an object is a boost python object from python

Is there a way I can test to see if an object is a boost class from within python by using the isinstance function?
I can see this visually doing something like object.__class__.__mro__, which will return something like (_user_library.SomeCppClass, Boost.Python.instance, object)
I couldn't figure out how to test this though in code, since I'm not sure where to import Boost.Python.class from.

How to share python instance to c++?

I'm using python for my c++ program's sub script language.
I bind my c++ class to python to use it in python side.
This system must can share(pass) c++ instance to python.
And even Python (script side) can create new instance also it must be share by c++ side too.
But python(or..java, c#)'s class type is reference type.
#MyClass class has class type member test
data1 = MyClass()
data2 = MyClass()
#so data1's test will point data2.test object
data1.test = data2.test
So it will be work like a c++'s pointer.
But in c++, class is not reference type.
So assignment operation will call = operator.
if =operator will not overloaded then it will work value copy.
ClassInstance1 = ClassInstance2
Well If you create some objects in python, and share (pass) to c++ side.
like...
Character* pChara = PythonSideObjectToCpp("data1");
The data work rule is different between c++ and python.
So i think c++ can not 1:1 match with pythonlike above code.
It will need more interface about get, set or control python's reference type member.
How do you think about this?
I don't think that python instance can extract to c++ purely.
Well... but it can extract python instance's clone object.

python ctypes sending pointer to structure as parameter to native library

I am trying to write a wrapper to a native library in Linux. Problem is this:
definition in c:
int mymethod(mystruct* ptr)
in python:
_lib.mymethod.argtypes = (ctypes.POINTER(mystruct),)
_lib.mymethod.restype = ctypes.c_int
s = mystruct()
_lib.mymethod(ctypes.byref(s))
# raises: expected LP_mystruct instance instead of pointer to mystruct
_lib.mymethod(ctypes.pointer(s))
# raises expected LP_mystruct instance instead of LP_mystruct
errors. How to pass a structure as a pointer to a native method ?
Thanks.
Mete
The problem is that the higher level "POINTER" from ctypes is, in Python, a different object than "a generic pointer" (ctypes.CArgObject by ctypes.byref)which is returned or a single number representing a memory address (which is what is returned by ctype's adrresof) - you can either annotate your function to receive a `ctypes.c_voidp and call it with _lib.mymethod(ctypes.addressof(a)) instead -
Or if you want to work on the stronged-typed side to avoid errors that would crash Python (a type error raises a Python exception instead - a wrong parameter passed to a C unction would cause a segmentation fault on the Python interpreter itself), you have to create a variable to hold the new "type" which is a POINTER to your structure - and then create an instance of this type with the address of your structure:
mystruct_pointer = ctypes.POINTER(mystruct)
_lib.mymethod.argtypes = (mystruct_pointer,)
_lib.mymethod.restype = ctypes.c_int
s = mystruct()
_lib.mymethod(mystruct_pointer.from_address(ctypes.addressof(s)))
(I know that this is an old question, but I think the accepted answer is an unnecessary workaround, so I want to leave this here for posterity.)
Actually ctypes should explicitly support using byref() to pass a pointer like that:
ctypes exports the byref() function which is used to pass parameters by reference. The same effect can be achieved with the pointer() function, although pointer() does a lot more work since it constructs a real pointer object, so it is faster to use byref() if you don’t need the pointer object in Python itself.
The likely cause of this is that you have defined your struct in more than one place (e.g. in different modules) - if the argtypes assignment sees one definition and the function call sees the other, this confusing error arises. In other words, ctypes tries to match two mystruct types that are (probably) identical in contents, and have the exact same name, but they are not the same type. As long as the base struct type is a single type object, it doesn't matter if you construct a pointer to it using pointer(), byref() or POINTER()() - ctypes will detect that the underlying (pointed-to) type is the same.
To verify if this is the case, try assert(_lib.mymethod.argtypes[0]._type_ == type(s)) right before calling the external function.

Categories

Resources