Structure to add a node id with correct type - c

I am trying to specify a node id on my server but don't understand the structure that I am supposed to follow. I followed the seemingly simple structure to change the node ID and didn't receive errors or warnings. I was successful in creating the nodes as seen below but not creating a node_id. I thought to add a simple node id I would follow the same structure and add the lines with $$$$ in them;
// opcua_server.c
#include "ua_types.h"
#define HANDLE_PDU1 15
const uint8_t EN_DISPLAYNAME_PDU1[] = "PDU1";
const UA_UTF8_string_t ENGLISH_TEXT[] = {
{0, 0}, {sizeof(EN_DISPLAYNAME_PDU1) - 1, EN_DISPLAYNAME_PDU1}};
void opcua_add_nodes(void) {
UA_Status_t status = 0;
// Add PDU1 Folder
UA_Folder_t PDU1;
UAServer_Init_config_structure_Folder(&PDU1);
PDU1.node_handle = HANDLE_PDU1;
PDU1.display_name_handle = HANDLE_PDU1;
UA_NodeId_Config_t randomHANDLE; // $$$$ Not creating node id
PDU1.node_id = randomHANDLE; // $$$$ Not creating node id
status = UAServer_Create_Folder(&PDU1);
if (status != 0) {
UA_SERVER_PRINTF("UAServer_Create_Folder returned: %d\n",
(uint16_t)status);
}
status = UAServer_Add_to_folder(folder.node_handle, PDU1.node_handle);
if (status != 0) {
UA_SERVER_PRINTF("UAServer_Add_to_objects_folder returned: %d\n",
(uint16_t)status);
}
}
// ua_types.h
typedef struct {
/**
* A mandatory unique identifier that identifies the node in the library.
* The value zero is invalid.
*/
uint32_t node_handle;
/**
* A mandatory unique identifier that allows the host to efficiently look up
* the
* node name text to display in a translate callback. The value zero is
* invalid.
*/
uint32_t display_name_handle;
/**
* An optional unique identifier that allows the host to efficiently look up
* the
* node description text to display in a translate callback. The value zero
* is
* invalid.
*/
uint32_t description_handle;
/**
* An optional visibility mask that restricts the visibility of the node
* depending
* on which user is logged in. The anonymous user is bit 0 and bits 1 - 15
* represent the corresponding users
*/
uint16_t user_visibility;
/**
* Specifies the namespace index for this node. The UA namespace is 0 and
* cannot
* be used. The default server namespace is 1. Other namespaces may be added
* to the configuration data structure.
*/
uint16_t namespace_index;
/**
* An optional parameter set that defines the NodeId for the node as a
* string
* or a GUID. If this parameter is set to default values then the SDK will
* assign
* an opaque node id to the node. Opaque node ids are easily decoded by the
* SDK
* and offer the best performance. Only populate this parameter set if your
* application requires it.
*/
UA_NodeId_Config_t node_id;
} UA_Base_t;
/*****************************************************************************/
/** \brief A configuration structure for Folder address space nodes.
*
*/
typedef UA_Base_t UA_Folder_t;
/*****************************************************************************/
/** \brief A configuration structure for View address space nodes.
*
*/
typedef UA_Folder_t UA_View_t;
/*****************************************************************************/
/** \brief A configuration structure for Method address space nodes.
*
*/
typedef struct {
/**
* Configuration common to all nodes
*/
UA_Base_t base_config;
/**
* The file size in bytes
*/
uint64_t size;
/**
* The file is writable
*/
bool_t writable;
/**
* An optional writable mask that restricts write access of the file
* depending
* on which user is logged in. The anonymous user is bit 0 and bits 1 - 15
* represent the corresponding users
*/
uint16_t user_writable;
} UA_File_t;

When you define PDU1, a node_id is already created and associated with it. You just need to access node_id and assign value for each of its elements.
Replace
UA_NodeId_Config_t randomHANDLE; // $$$$ Not creating node id
PDU1.node_id = randomHANDLE; // $$$$ Not creating node id
with
PDU1.node_id.identifier_type = xxxx; // xxxx, yyyy, zzz is whatever valid value for their type.
PDU1.node_id.string_identifier = yyyy;
PDU1.node_id.guid_identifier = zzzz;

Turns out I needed to specify the identifier type (which I did by looking at the identifier types) and set it equal to opcua_node_encoding_string. The result is a string node id that I set out to create.
//Add PDU1 Folder
UA_Folder_t PDU1;
UAServer_Init_config_structure_Folder(&PDU1);
PDU1.node_handle = HANDLE_PDU1;
PDU1.display_name_handle = HANDLE_PDU1;
PDU1.node_id.identifier_type = opcua_node_encoding_string;
const char TEST_STRING_ID2[] = "PDU1";
PDU1.node_id.string_identifier.length = sizeof(TEST_STRING_ID2) - 1;
PDU1.node_id.string_identifier.data = (uint8_t*)TEST_STRING_ID2;
status = UAServer_Create_Folder(&PDU1);
if (status != 0)
{
UA_SERVER_PRINTF("UAServer_Create_Folder returned: %d\n", (uint16_t)status);
}
status = UAServer_Add_to_folder(folder.node_handle, PDU1.node_handle);
if (status != 0)
{
UA_SERVER_PRINTF("UAServer_Add_to_objects_folder returned: %d\n", (uint16_t)status);
}

Related

Get the name of a coll object in Max C API

I am writing a Max MSP external.
I am lost in Max C API documentation since hours and couldn't find a way to get the name of a coll object from Max C API.
https://cycling74.com/sdk/max-sdk-8.0.3/html/index.html
If the object is | coll foo | , foo is the symbol I want to get.
I am able to iterate over a patcher and get pointers to all boxes and then to objects by calling jbox_get_object() with pointers to boxes. I tried getting many attributes of the objects I got and everything works ok.
I can't seem to find where the data I want to get is stored and what is it called.
I would appreciate some help.
Thank you.
[coll] is very sparsely documented, you should ask on the Cycling74 dev-forum. Below is what I do in [posit] after traversing the patcher to find a coll’s box. hth /*j
#include “coll.h”
<snip>
t_object *o;
t_coll *collob;
t_object *jb;
t_symbol *collname;
<snip>
o = jbox_get_object(jb);
collob = (t_coll *)o;
collname = (t_symbol *)collob->c_x->c_sym;
</snip>
Thank you user12106422! This is how I have implemented this in my iterator function and it works perfectly.
#include "coll.h"
//in your iterator function ..
long patcher_iterator(<replace this with your external type> *x, t_object *b) {
//check if object is a coll
if(strncmp(object_classname( jbox_get_object(b) )->s_name, "coll",4) == 0){
t_coll *collobject;
t_symbol *collname;
collob = (t_coll *)jbox_get_object(b);
collname = (t_symbol *)collobject->c_x->c_sym;
post("--The name of the coll is (%s) ", collname->s_name);
}
}
I would also like to share coll.h here for common benefit.
/* -------- coll.c -- the collection object --------------- */
#include "ext.h"
// #include "edit.h"
#include "ext_wind.h"
#include "ext_common.h"
#include "ext_strings.h"
#include "ext_critical.h"
#define C_EMBED 1
/* ddz 06/09/94:
* fixed interspersed (entremele) use of next and prev messages
* added assistance for third outlet
* prototyped functions and removed voids
* fixed truncating on sorts
*/
/* sde use to fill the read and write flags */
#define FILE_DIALOG 1 /* use dialogs to get file name */
#define FILE_NAMED 2 /* symbol specifies file name */
#define Index_Integer 1
#define Index_Symbol 2
typedef struct celem { /* doubly linked list element */
short e_size;
short e_extra;
long e_index;
t_symbol *e_assoc;
struct celem *e_next;
struct celem *e_prev;
t_atom e_data[1]; /* dummy */
} t_celem;
typedef struct xcoll {
t_object c_ob;
void *c_data; // linklist
//t_celem c_head; /* head of list elements */
t_celem *c_next; /* element to be returned by "next" */
t_celem *c_prev; /* element to be returned by "prev" */
void *c_out2; /* next "end" signal outlet */
char c_read,c_write; /* flags for reading & writing */
char c_freeing,c_saveme;
char c_embed; /* embed in owning patcher? */
t_symbol *c_sym; /* associated symbol? */
struct ed *c_edit; /* edit window */
short c_refcount; /* reference count */
struct coll *c_refcoll; /* list of "colls" that reference this xcoll */
/* sde filename, volume, and MAX type */
t_symbol *c_fn;
short c_vol;
short c_bin;
long c_type; /* type of the file that was read in */
short c_modified;
long c_filetype; /* for filetype message -- allowed types */
long c_modcount;
} t_xcoll;
typedef struct coll {
t_object c_ob;
t_xcoll *c_x;
t_symbol *c_sym;
void *c_out2;
/* sde third outlet bangs after reading data */
void *c_out3;
void *c_out4;
struct coll *c_nextref; /* next in the list of colls that share this coll's xcoll */
void *c_owner;
long c_nosearch;
} t_coll;

Doxygen: group data structures on file level

I would like to use the Doxygen grouping mechanism for data structures. I'm already using it for functions and it works well so far. What I've experienced so far fits to the documentation regarding member groups of a single type (e.g. function only) or mixed type (e.g. typedefs and functions).
Now I tried to extend these member groups with data structures, and this fails exceptionally. Data structures are always a top section on its own. My tries so far:
Put a data structures definition inside an existing mixed type member group. -> Data structure is still documented in a separate top level section.
/**
* \file doxytest.h
*/
/**
* \name Iteration API
* \brief Some documentation. Group will be on top level.
*/
/// #{
/**
* \brief For no reason this is not part of the member group.
*/
typedef struct {
/**
* \brief Some mask
*/
uint32_t mask;
} filter_t;
/**
* \brief Some variable
*/
extern const uint32_t MODE_FILTER_MASK;
/**
* \brief Curiously this IS part of the member group.
*/
typedef bool (*for_each_cb)(const void *obj, void *opaque);
/**
* \brief Some function
*/
uint32_t filter_id_filter_set(size_t ids_num, ...);
/// #}
Side by Side of final Doxygen output and desired Doxygen output (Photoshopped)
Creating a group solely consisting of data structures. -> Data structures are documented in a separate top level section and the documentation block for this group vanishes completely.
/**
* \file doxytest2.h
*/
/**
* \name Structures
* \brief This documentation block will not show up
* in the final file documentation. It is completely lost.
*/
/// #{
/**
* \brief Won't show up in group/section "Structures"
*/
typedef struct {
/**
* \brief Some mask
*/
uint32_t mask;
} filterA_t;
/**
* \brief Won't show up as well
*/
typedef struct {
/**
* \brief Some mask
*/
uint32_t mask;
} filterB_t;
/// #}
/// Some struct that should not show up in group "Structures"
typedef struct {
int bar;
} someStruct;
Side by Side of final Doxygen output and desired Doxygen output (Photoshopped)
Use a module and add the data structures mit \ingroup. -> Data structure pops up in the module, but the file documentation still looks the same as above
Using \nosubgrouping command on file level documentation. -> No changes at all to file documentation page.
/**
* \file doxytest.h
* \nosubgrouping
*/
I would like that the documentation for file doxytest.h/doxytest2.h displays data structures in the group they were defined in.
The programming language is C, but I'm very limited in terms of changing the code to fit documentation needs. Doxygen version is 1.8.16. The configuration file is almost default. (I left out stuff like project name and input settings)
OPTIMIZE_OUTPUT_FOR_C = YES
EXTRACT_ALL = YES
EXTRACT_STATIC = YES
SORT_MEMBER_DOCS = NO
DISABLE_INDEX = NO
Any help appreciated.
It took me several months to find, but the answer was deceptively simple.
You just need to enable INLINE_SIMPLE_STRUCTS:
# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
# with only public data fields or simple typedef fields will be shown inline in
# the documentation of the scope in which they are defined (i.e. file,
# namespace, or group documentation), provided this scope is documented. If set
# to NO, structs, classes, and unions are shown on a separate page (for HTML and
# Man pages) or section (for LaTeX and RTF).
# The default value is: NO.
INLINE_SIMPLE_STRUCTS = YES
The fact that the data structures are "simple" is only a consideration of every member being publicly accessible, not the number of entries.

How do I document functions with return type of struct properly using doxywizard?

Although I have looked everywhere I think I possibly could to find my answer, I have not been able to figure out how to correctly document the function "struct Entity * NewEntity()" so that it appears documented when doxywizard runs.
It just keeps telling me: "warning: Member NewEntity() (function) of file entity.h is not documented."
Yet, the code is:
/***********************************************************************************************//*
* #fn struct Entity* NewEntity()
*
* #brief Initialises single entity.
* #return null if it fails, else finds empty spot in entity manager to use to make a new entity
* #author br66
* #date 3/30/2017
**************************************************************************************************/
struct Entity* NewEntity()
{
int i;
for (i = 0; i < 255; i++)
{
if (_entityM[i].m_active == 0)
{
// clear that space, just in case there's anything left over from its last use
memset(&_entityM[i], 0, sizeof(struct Entity));
_entityM[i].m_active = 1;
// any entity defaults? stay tooooooned
_entity_max_recorded++;
return &_entityM[i];
}
}
return NULL;
}
Reading the documentation, it tells me to make sure the header file is documented, but it has not changed anything and I still get that warning.
You have two comment blocks. /****...***/ /* #fn... */
The second comment is not looked at by doxygen.
A doxygen comment block should start with an extra '*' /** #fn... */ .

C struct instance is missing members after copying it to Swift

I'm using C's inotify library, through a wrapper in Swift. The idea is to provide a Swift Package Manager library that gives basic File System events support in Linux.
Almost everything works. Except that here, I can't seem to be able to copy the inotify_event member name:
let bufferLength = Int(MemoryLayout<inotify_event>.size + NAME_MAX + 1)
let buffer = UnsafeMutablePointer<CChar>.allocate(capacity: bufferLength)
var fileSystemEvent : FileSystemEvent?
var currentIndex: Int = 0
let readLength = read(Int32(self.fileDescriptor), buffer, bufferLength)
while currentIndex < readLength {
var event = withUnsafePointer(to: &buffer[currentIndex]) {
return $0.withMemoryRebound(to: inotify_event.self, capacity: 1) {
return $0.pointee
}
}
if event.len > 0 {
fileSystemEvent = FileSystemEvent(
watchDescriptor: WatchDescriptor(event.wd),
name: "", //String(cString: event.name),
mask: event.mask,
cookie: event.cookie,
length: event.len
)
}
currentIndex += MemoryLayout<inotify_event>.stride + Int(event.len)
}
I would want to do:
name: String(cString: event.name), but then the compiler throws an error:
`value of type 'inotify_event' has no member 'name'`
I can't find any clues as to why this happens, or as to how I can access the name member. Here is the struct's declaration in inotify.h:
/*
* struct inotify_event - structure read from the inotify device for each event
*
* When you are watching a directory, you will receive the filename for events
* such as IN_CREATE, IN_DELETE, IN_OPEN, IN_CLOSE, ..., relative to the wd.
*/
struct inotify_event {
__s32 wd; /* watch descriptor */
__u32 mask; /* watch mask */
__u32 cookie; /* cookie to synchronize two events */
__u32 len; /* length (including nulls) of name */
char name[0]; /* stub for possible name */
};
What's going on here?
Thanks in advance :)
PS: here's my full project, if you need more information.
The name field is defined as a zero-length array:
char name[0]; /* stub for possible name */
and those are not
imported into Swift. A possible solution is to compute the offset to the
start of the name string within the received buffer:
fileSystemEvent = FileSystemEvent(
watchDescriptor: WatchDescriptor(event.wd),
name: String(cString: buffer + currentIndex + MemoryLayout<inotify_event>.size),
mask: event.mask,
cookie: event.cookie,
length: event.len)

Compilation error "has no member named" for a union member

I see this compilation error "has no member named" for some of the union elements.
snmp_xmas.c:129: error: 'xmas_datatype_value_t' has no member named 'int8'
snmp_xmas.c:132: error: 'xmas_datatype_value_t' has no member named 'int16'
I dont see any issue with the member definion. The union definion is as follows.
typedef union {
/**
* Value for XMAS_ITEM_DATATYPE_BITS
*/
xmas_datatype_bits_t bits;
/**
* Value for XMAS_ITEM_DATATYPE_BOOL
*/
xmas_datatype_bool_t boolean;
/**
* Value for XMAS_ITEM_DATATYPE_CERRNO
*/
xmas_datatype_cerrno_t cerrno;
/**
* Value for XMAS_ITEM_DATATYPE_DATETIME
*/
xmas_datatype_datetime_t datetime;
/**
* Value for XMAS_ITEM_DATATYPE_EMPTY
*/
xmas_datatype_empty_t empty;
/**
* Value for XMAS_ITEM_DATATYPE_ENUM
*/
xmas_datatype_enum_t enumeration;
/**
* Value for XMAS_ITEM_DATATYPE_IDENTITYREF
*/
xmas_datatype_identityref_t identityref;
/**
* Value for XMAS_ITEM_DATATYPE_INT16
*/
xmas_datatype_int16_t int16;
/**
* Value for XMAS_ITEM_DATATYPE_INT32
*/
xmas_datatype_int32_t int32;
/**
* Value for XMAS_ITEM_DATATYPE_INT64
*/
xmas_datatype_int64_t int64;
/**
* Value for XMAS_ITEM_DATATYPE_INT8
*/
xmas_datatype_int8_t int8;
/**
* Value for XMAS_ITEM_DATATYPE_INTF
*/
xmas_datatype_intf_t *intf;
/**
* Value for XMAS_ITEM_DATATYPE_IPV4_ADDR
*/
xmas_datatype_ipv4_addr_t ipv4_addr;
/**
* Value for XMAS_ITEM_DATATYPE_IPV6_ADDR
*/
xmas_datatype_ipv6_addr_t *ipv6_addr;
/**
* Value for XMAS_ITEM_DATATYPE_IP_ADDR
*/
xmas_datatype_ip_addr_t *ip_addr;
/**
} xmas_datatype_value_t;
All the xmas datatypes are defined in a single header file and is included in my .c file which refers the union members. The code snippet is pasted below.
cerrno
xmibd_convert_xmas_to_XXX(xmas_item_datatype_t *xmas_datatype,
xmas_datatype_value_t *xmas_value,
struct sa_do_value **ret_value)
{
:
:
:
switch (*xmas_datatype) {
case XMAS_ITEM_DATATYPE_BITS:
out_value = sa_do_value_new_unsigned_long(xmas_value->bits);
break;
case XMAS_ITEM_DATATYPE_BOOL:
out_value = sa_do_value_new_boolean(xmas_value->boolean);
break;
case XMAS_ITEM_DATATYPE_CERRNO:
out_value = sa_do_value_new_unsigned_int(xmas_value->cerrno);
break;
case XMAS_ITEM_DATATYPE_EMPTY:
out_value = sa_do_value_new_boolean(xmas_value->empty);
break;
case XMAS_ITEM_DATATYPE_DATETIME:
out_value = sa_do_value_new_datetime(xmas_value->datetime);
break;
case XMAS_ITEM_DATATYPE_INT8:
out_value = sa_do_value_new_byte(xmas_value->int8);
break;
case XMAS_ITEM_DATATYPE_INT16:
out_value = sa_do_value_new_short(xmas_value->int16);
break;
:
:
}
Any pointers to the possible issue would be highly appreciated.
Thanks,
The issue was related to a duplicate obsolete path for the header file mentioned in the Makefile. It was referring to the wrong path, so obviously my changes weren't getting affected.

Resources