PublishModule
module increments or decrements a value cyclically. It used a basic C moduleEventModule
module allows to click on a toggle to set if the first module should increment or decrement the value, and shows the valueapplications.xml
XML file has to be modified to switch from a basic C module implementation to a configured C module.
applications.xml
XML file, by modifying the PublishModule
configuration:<application name="publishAppli"> <modules> <cModule name="PublishModule"> <cImplementation path="PublishModule" nativeConfig="nativeConf.xml"/> <interfaces> <eventReceived service="event"/> <cyclic service="published" frequency="200ms" attach="attach"/> </interfaces> </cModule> </modules> </application>
PublishModule
project in CodeBlocks. See the Setting a CodeBlocks project for a C module for more information on how to do it.
event
service. We will specify a receive
function in the C interface for this service notification. As this service has one boolean data, we will have one bool
argument:#include <stdbool.h> __declspec(dllexport) void receive(bool state);We also have one service publication for the
published
service. We need to specify a function to set the associated function by the framework, and a function which will be called by the framework to perform the publication (because published
is a cyclic service):static void (*InvokerInst)(int); __declspec(dllexport) void publish(); __declspec(dllexport) void setInvoker(void (*InvokerInst)(int));
setInvoker(void (*InvokerInst)(int))
allows to set the address of the function that the C code must call to invoke the published
servicestatic void (*InvokerInst)(int)
is the memorization of the pointer to this functionstatic int count = 0; static int step = 1;We have therefore the following header:
#include <stdbool.h> static int count = 0; static int step = 1; static void (*InvokerInst)(int); __declspec(dllexport) void publish(); __declspec(dllexport) void receive(bool state); __declspec(dllexport) void setInvoker(void (*InvokerInst)(int));
setInvoker(void (*InvokerInst)(int))
will be called:void setInvoker(void (*Invoker)(int)) { InvokerInst = Invoker; }When we receive the
event
service, we will trigger the receive
function:void receive(bool state) { if (state) { step = -1; } else { step = 1; } }And now when we are cyclicallly called for the
published
service, we trigger the publish
function:void publish() { count += step; InvokerInst(count); }The final source code is:
#include <stdio.h> #include "module1.h" // this is our C header #include <windows.h> #include <stdbool.h> void publish() { count += step; InvokerInst(count); } void receive(bool state) { if (state) { step = -1; } else { step = 1; } } void setInvoker(void (*Invoker)(int)) { InvokerInst = Invoker; }
<nativeConfig libPath="org.da.testutils.clibrary.CLibrary"> </nativeConfig>We will see in the next paragraph how we will specify this class. But for the moment, we need to specify the bridge from the services to* the C functions.
published
invoke service will be bridged to the publish
function. There is only one argument, which is the counter value:<nativeConfig libPath="org.da.testutils.clibrary.CLibrary"> <invokeServices> <invokeService name="published"> <argument name="value" /> </invokeService> </invokeServices> </nativeConfig>
event
notified service will be bridged to the event
function. There is only one argument, which is the bolean representing the state::<nativeConfig libPath="org.da.testutils.clibrary.CLibrary"> <notifServices> <notifService name="event"> <argument name="event" /> </notifService> </notifServices> </nativeConfig>
<nativeConfig libPath="org.da.testutils.clibrary.CLibrary"> <invokeServices> <invokeService name="published"> <argument name="value" /> </invokeService> </invokeServices> <notifServices> <notifService name="event"> <argument name="event" /> </notifService> </notifServices> </nativeConfig>
com.sun.jna.Library
interface which will as as a the bridge between the natvie code and the framework:public interface CLibrary extends Library { }The
event
service is a notification and is bridged with the receive
function:public interface CLibrary extends Library { @SignatureTag(type=SignatureType.NOTIFICATION, name="event") public void receive(boolean state); } }The
published
service is an invocation and is bridged with the setInvoker
function:public interface CLibrary extends Library { @SignatureTag(type=SignatureType.CYCLIC_SERVICE, name="published") public void publish(); @SignatureTag(type=SignatureType.INVOCATION, name="published") public void setInvoker(Invoker callback); public interface Invoker extends Callback { void invoke(int value); } }We have the following code for the interface:
public interface CLibrary extends Library { @SignatureTag(type=SignatureType.NOTIFICATION, name="event") public void receive(boolean state); @SignatureTag(type=SignatureType.CYCLIC_SERVICE, name="published") public void publish(); @SignatureTag(type=SignatureType.INVOCATION, name="published") public void setInvoker(Invoker callback); public interface Invoker extends Callback { void invoke(int value); } }Now we must generate a jar file with this interface, and add this jar file to the decployment for our module:
<application name="publishAppli"> <deployment> <lib url="CLibrary.jar" /> </deployment> <modules> <cModule name="PublishModule"> <cImplementation path="PublishModule2" nativeConfig="nativeConfig.xml"/> <interfaces> <eventReceived service="event"/> <cyclic service="published" frequency="200ms" attach="attach"/> </interfaces> </cModule> </modules> </application>
Copyright 2017-2020 Dassault Aviation. All Rights Reserved. Documentation and source under the LGPL v3 licence