4

Issue

I'm trying to call CAPL general functions (in my case timeNowNS) but I don't know if it's possible.

capl general functions

What I'm using?

I'm using Python 3.7 and Vector CANoe 11.0.

The connection is done using the .NET CANoe API. This is how i've accesed the DLLs.


import clr
sys.path.append("C:\Program Files\Vector CANoe 11.0\Exec64")  # path to CANoe DLL Files
clr.AddReference('Vector.CANoe.Interop')                      # add reference to .NET DLL file
import CANoe                                                  # import namespace from DLL file

What I've tried?

I opened the CANoe simulation succesfully, started the measure and I'm having access to signals, env variables and sys variables.

Then I've created the CAPL Object and tried using the GetFunction method to obtain the CAPLFunction object so i could call it.

def begin_can(self, sCfgFile, fPrjInitFunc = None):
     self.open_can()
     self.load_can_configuration(sCfgFile)
     self.start_can_measurement(fPrjInitFunc)

def open_can(self):
    self.mCANoeApp = CANoe.Application()
    self.mCANoeMeasurement = CANoe.Measurement(self.mCANoeApp.Measurement)
    self.mCANoeEnv = CANoe.Environment(self.mCANoeApp.Environment)
    self.mCANoeBus = CANoe.Bus(self.mCANoeApp.get_Bus("CAN"))
    self.mCANoeSys = CANoe.System(self.mCANoeApp.System)
    self.mCANoeNamespaces = CANoe.Namespaces(self.mCANoeSys.Namespaces)
    self.mCANoeCAPL = CANoe.CAPL(self.mCANoeApp.CAPL)
    self.mCANoeCAPL.Compile()

def getFunction(self):
        function1 = self.mCANoeCAPL.GetFunction('timeNowNS')

        # here I tried also CANoe.CAPLFunction(self.mCANoeCAPL.GetFunction('timeNowNS')) 
        # but i got attribute error: doesn't exist or something like that 

        result = function1.Call()

Expected results

I should get the current simulation time using this function.

Actual results

Using the above code I get:

**COMException**: Catastrophic failure (Exception from HRESULT: 0x8000FFFF (E_UNEXPECTED))
   at CANoe.ICAPL5.GetFunction(String Name)

I've tried different variations of the code but didn't get anywhere.

Is it possible to be a hardware problem? Should I do some settings in the CANoe Simulation?

If you need more information, please ask me! Thanks in advance

Update: I've added a photo of my measure setup after adding the CAPL block

Measure setup

Stefan Muresan
  • 101
  • 2
  • 10

2 Answers2

3

You have to write a CAPL function in which you call timeNowNS. This CAPL function can then be called from Python in the way you have implemented.

GetFunction only works with (user-written) CAPL functions. You cannot call CAPL intrinsics (i.e. built-in CAPL functions) directly.

Put this into a CAPL file:

int MyFunc()
{
  return timeNowNS();
}

and call like this from Python:

def getFunction(self):
    function1 = self.mCANoeCAPL.GetFunction('MyFunc')
    result = function1.Call()
MSpiller
  • 3,500
  • 2
  • 12
  • 24
  • Thank you so much for your answer, @M. Spiller ! I've added my function to a CAPL file and i've tried it and i get an error: `**AttributeError: '__ComObject' object has no attribute 'Call'**`. And i've tried to do a cast to a CAPLFunction: `function1 = CANoe.CAPLFunction(self.mCANoeCAPL.GetFunction('MyFunc'))` but the result is **None**. Do you have any idea what went wrong? – Stefan Muresan Aug 19 '19 at 09:01
  • 1
    Hmm. First of all the cast should not be necessary. Some things to try. 1. the return value of your CAPL function should be int. 2. The CAPL function has to be defined in a block which is part of CANoe's measurement setup (not simulation setup). Does that help? – MSpiller Aug 19 '19 at 09:12
  • M. Spiller, the return value is int so i'm ok here and you were right, i had declared the function in a block in simulation setup, my mistake. I've inserted a block in measure setup and added the function but still doesn't work, i get the same error: `AttributeError: '__ComObject' object has no attribute 'Call'`. I've updated the post with a picture of my measure setup, it looks ok to you? Thank you again! – Stefan Muresan Aug 19 '19 at 10:13
  • 1
    Looks ok. Can you access other properties of the CAPLFunction object? E.g. try `print(function1.ParameterCount)`. You could also `print(function1)` to make sure a valid function object was returned. – MSpiller Aug 19 '19 at 10:39
  • So if I try it without cast to CAPLFunction i get the same error: `System.__ComObject AttributeError: '__ComObject' object has no attribute 'ParameterCount'` But if I try with the cast, like this: `function2 = CANoe.CAPLFunction(mCANoeCAPL.GetFunction('MyTime')) print(function2) print(function2.ParameterCount) result = function2.Call() print(result)` I get the following output: `System.__ComObject 0 None ` – Stefan Muresan Aug 19 '19 at 11:26
  • By the way, i found something [here](https://assets.vector.com/cms/content/know-how/_application-notes/AN-AND-1-117_CANoe_CANalyzer_as_a_COM_Server.pdf), in chapter 2.7 that says that **The assignment of a CAPL function to a variable can only be done in the OnInit event handler of the Measurement object.**. Maybe this is the problem? – Stefan Muresan Aug 19 '19 at 11:31
  • Could be. Try the following in your code, not in an event-handler: `self.mCANoeCAPL.GetFunction('MyFunc').Call()` – MSpiller Aug 19 '19 at 11:40
  • I've just tried it and got the initial error in my post: `COMException: Catastrophic failure (Exception from HRESULT: 0x8000FFFF (E_UNEXPECTED)) at CANoe.ICAPL5.GetFunction(String Name)`. I don't know what's the problem but thank you so much for the info, i will try making some adjustments and see. – Stefan Muresan Aug 19 '19 at 11:54
3

After a long session of try and error and the help of @m-spiller I found the solution.

function2 = None

   def open_can(self):
        self.mCANoeApp = CANoe.Application()
        self.mCANoeMeasurement = self.mCANoeApp.Measurement   # change here: no cast necessary
        self.mCANoeEnv = CANoe.Environment(self.mCANoeApp.Environment)
        self.mCANoeBus = CANoe.Bus(self.mCANoeApp.get_Bus("CAN"))
        self.mCANoeSys = CANoe.System(self.mCANoeApp.System)
        self.mCANoeNamespaces = CANoe.Namespaces(self.mCANoeSys.Namespaces)
        self.mCANoeCAPL = CANoe.CAPL(self.mCANoeApp.CAPL)
        self.mCANoeMeasurement.OnInit += CANoe._IMeasurementEvents_OnInitEventHandler(self.OnInit)  
        # change here also: explained below

    def OnInit(self):
        global function2
        function2 = CANoe.CAPLFunction(mCANoeCAPL.GetFunction('MyTime')) # cast here is necessary

    def callFunction(self):
        result = function2.Call()

What was the problem with the initial code?

The problem was that i tried to assign a function to a variable after the measure has started.
As stated here in chapter 2.7, the assignment of a CAPL Function to a variable can only be done in the OnInit event handler of the Measurement object.

I've added this line, studying the documentation:

self.mCANoeMeasurement.OnInit += CANoe._IMeasurementEvents_OnInitEventHandler(self.OnInit)

After adding it, on init the OnInit function was executed and the CAPL function was assigned to a variable and afterwards i could use that variable to call the function.

Thank you again, @m-spiller !

Stefan Muresan
  • 101
  • 2
  • 10