-1

I am a bit confused for my implementation. I have a Python script to be embedded into C++.

import urllib.request
import ssl
import suds.transport.http
from suds.client import Client

class UnverifiedHttpsTransport(suds.transport.http.HttpTransport):
  def __init__(self, *args, **kwargs):
     super(UnverifiedHttpsTransport, self).__init__(*args, **kwargs)
  def u2handlers(self):
     handlers = super(UnverifiedHttpsTransport, self).u2handlers()
     context = ssl.create_default_context()
     context.check_hostname = False
     context.verify_mode = ssl.CERT_NONE
     handlers.append(urllib.request.HTTPSHandler(context=context))
     return handlers

url="https://xxxxxest.com/datamanagement.asmx?WSDL"
client = Client(url, transport=UnverifiedHttpsTransport())

def ReadDataTest():
  result = client.service.ReadTestData()
  return result

def ReadGridData():
  result = client.service.ReadGridData()  
  return result

def main():
  result=ReadGridData()
  print(result)

if __name__ == "__main__":
  main()

Then sample_main.cpp has plugin lib sample_plugin.cpp.

sample_plugin.cpp has python embedded code as follows.

  Py_Initialize();
  pName = PyUnicode_DecodeFSDefault("web_interface");
  pModule = PyImport_Import(pName);
  Py_DECREF(pName);
  if (pModule != NULL) {
    pFunc_readtest = PyObject_GetAttrString(pModule, "ReadDataTest");
    if (pFunc_readtest && PyCallable_Check(pFunc_readtest)) {
      pValue = PyObject_CallObject(pFunc_readtest, NULL);
      if(pValue != NULL) {
         printf("Result of call: %s\n", pValue);
         Py_DECREF(pValue);
      }
    }
    Py_XDECREF(pFunc_readtest);
    Py_DECREF(pModule);
  }else{
    PyErr_Print();
    printf("Can't call python \n");
  }
  Py_FinalizeEx();

When I run sample_main.exe, I have errors as

Traceback (most recent call last):
  File "/opt/nvidia/deepstream/deepstream-5.0/sources/apps/sample_apps/deepstream-test3/web_interface.py", line 2, in <module>
    import ssl
  File "/usr/lib/python3.6/ssl.py", line 101, in <module>
    import _ssl             # if we can't import it, let the error propagate
ImportError: /usr/lib/python3.6/lib-dynload/_ssl.cpython-36m-aarch64-linux-gnu.so: undefined symbol: PyExc_OSError
Error in sys.excepthook:
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/apport_python_hook.py", line 63, in apport_excepthook
    from apport.fileutils import likely_packaged, get_recent_crashes
  File "/usr/lib/python3/dist-packages/apport/__init__.py", line 5, in <module>
    from apport.report import Report
  File "/usr/lib/python3/dist-packages/apport/report.py", line 30, in <module>
    import apport.fileutils
  File "/usr/lib/python3/dist-packages/apport/fileutils.py", line 23, in <module>
    from apport.packaging_impl import impl as packaging
  File "/usr/lib/python3/dist-packages/apport/packaging_impl.py", line 24, in <module>
    import apt
  File "/usr/lib/python3/dist-packages/apt/__init__.py", line 23, in <module>
    import apt_pkg
ImportError: /usr/lib/python3/dist-packages/apt_pkg.cpython-36m-aarch64-linux-gnu.so: undefined symbol: PyExc_ValueError

Original exception was:
Traceback (most recent call last):
  File "/opt/nvidia/deepstream/deepstream-5.0/sources/apps/sample_apps/deepstream-test3/web_interface.py", line 2, in <module>
    import ssl
  File "/usr/lib/python3.6/ssl.py", line 101, in <module>
    import _ssl             # if we can't import it, let the error propagate
ImportError: /usr/lib/python3.6/lib-dynload/_ssl.cpython-36m-aarch64-linux-gnu.so: undefined symbol: PyExc_OSError

The error is removed when I include Py_Initialize(); inside sample_main.cpp.

Why is it necessary to include Py_Initialize(); inside sample_main.cpp?

Is that the right way to do that? What are the things I need to care inside

sample_main.cpp

for memory leak or anything other issues?

halfer
  • 19,824
  • 17
  • 99
  • 186
batuman
  • 7,066
  • 26
  • 107
  • 229
  • _Can somebody explain why it is necessary to include `Py_Initialize()`_ - that's what documentation is for https://docs.python.org/3/c-api/intro.html#embedding-python – Maxim Egorushkin Aug 24 '20 at 10:30

1 Answers1

-1

In an application embedding Python, the Py_Initialize() function must be called before using any other Python/C API functions

First words of the documentation, https://docs.python.org/3/c-api/init.html

tevemadar
  • 12,389
  • 3
  • 21
  • 49
  • Yes I called it inside sample_plugin.cpp shown above. Now the thing is I still need to call again inside `sample_maincpp` – batuman Aug 24 '20 at 07:19
  • So that means, for such implementation as mine, Py_Initialize(); and Py_FinalizeEx(); are called inside main.cpp. – batuman Aug 24 '20 at 07:22
  • Yes: if you do not call it, no one else will do. – tevemadar Aug 24 '20 at 08:01
  • Your don't answer my question. Why it is not enough to call inside plugin lib? Why need to call in main, not in lib? – batuman Aug 24 '20 at 08:53
  • In runtime, library code does not behave differently from "your" code, so it is expected to work. But, no other calls to Python can be made prior to that. This is why seeing a [mre] would be nice. – tevemadar Aug 24 '20 at 13:31