I'm migrating some lines coded on C to C++/CLI (UI Windows Form based on .NET). One of my problems comes when I try to do this kind of assignation:
myCallbacks.cbf_data_write = this->dataWriteFunc;
In this case, dataWriteFunc is defined as:
PNIO_IOXS dataWriteFunc(PNIO_UINT32, PNIO_DEV_ADDR *, PNIO_UINT32, PNIO_UINT8 *, PNIO_IOXS);
And myCallbacks is declared as
PNIOD_CBF_FUNCTIONS myCallbacks;
with
typedef struct {
PNIO_UINT32 size; /* size of struct = sizeof(PNIO_CBF_FUNCTIONS) */
PNIO_CBF_DATA_WRITE cbf_data_write; /* mandatory */
PNIO_CBF_DATA_READ cbf_data_read; /* mandatory */
PNIOD_CBF_ASYNC_REC_READ cbf_async_rec_read; /* mandatory */
PNIOD_CBF_ASYNC_REC_WRITE cbf_async_rec_write; /* mandatory */
PNIOD_CBF_SYNC_ALARM_DONE cbf_sync_alarm_done; /* mandatory */
PNIOD_CBF_ASYNC_CONNECT_IND cbf_async_connect_ind; /* mandatory */
PNIOD_CBF_ASYNC_OWNERSHIP_IND cbf_async_ownership_ind; /* mandatory */
PNIOD_CBF_ASYNC_INDATA_IND cbf_async_indata_ind; /* mandatory */
PNIOD_CBF_SYNC_DISCONNECT_IND cbf_sync_disconnect_ind; /* mandatory */
PNIOD_CBF_SYNC_DATA_STATUS_IND cbf_sync_data_status_ind; /* mandatory */
PNIOD_CBF_ASYNC_PRM_END_IND cbf_async_prm_end_ind; /* mandatory */
PNIOD_CBF_SYNC_STOPPED cbf_sync_device_stopped; /* mandatory */
PNIOD_CBF_ASYNC_IRT_INIT_INPUTS cbf_async_irt_init_inputs; /* mandatory for IRT top */
PNIOD_CBF_SYNC_CP_STOP_REQ cbf_sync_cp_stop_req; /* optional */
PNIOD_CBF_SYNC_START_LED_FLASH cbf_sync_start_led_flash; /* optional */
PNIOD_CBF_SYNC_STOP_LED_FLASH cbf_sync_stop_led_flash; /* optional */
PNIOD_CBF_RESERVED
} ATTR_PACKED PNIOD_CBF_FUNCTIONS;
Also:
typedef PNIO_IOXS (*PNIO_CBF_DATA_WRITE) /* write data to IO stack (local ==> remote) */
(PNIO_UINT32 DevHndl, /* Handle for Multidevice */
PNIO_DEV_ADDR * pAddr, /* geographical address */
PNIO_UINT32 BufLen, /* length of the submodule input data */
PNIO_UINT8 * pBuffer, /* Ptr to data buffer to write to */
PNIO_IOXS Iocs); /* remote (io controller) consumer status */
So, what exactly I'm doing wrong? VS2012 gives me next error:
Error 4 error C2440: '=' : cannot convert from 'PNIO_IOXS (__thiscall CP1626::* )(PNIO_UINT32,PNIO_DEV_ADDR *,PNIO_UINT32,PNIO_UINT8 *,PNIO_IOXS)' to 'PNIO_CBF_DATA_WRITE' c:\users\hp\documents\visual studio 2012\projects\ui_cp1626\ui_cp1626\Profinet_IDevice.h 513 1 UI_CP1626
What's the correct form to associate callbacks in this case?
Thank you in advance.
You're trying to convert thiscall function (non-static class member function) to ordinary function. The problem is non-static class members take extra implicit argument, the pointer to class object aka this, so dataWriteFunc's implicit signature is:
PNIO_IOXS dataWriteFunc(CP1626 *this, PNIO_UINT32, PNIO_DEV_ADDR *,
PNIO_UINT32, PNIO_UINT8 *, PNIO_IOXS);
, note the 1st argument, it's implicit presence is what gives function "__thiscall" attribute. If you declare this function as
static PNIO_IOXS dataWriteFunc(PNIO_UINT32, PNIO_DEV_ADDR *,
PNIO_UINT32, PNIO_UINT8 *, PNIO_IOXS);
then the error will go away. Note that inside static methods this is not available.
Related
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;
I have below code in a C header file:
/** \brief Forward declaration for instance object. */
typedef struct CbData_t CbData;
/**
* \brief Callback function prototype.
*
* \param cbData [OUT] Callback Data. Refer #CbData
* \return None.
*/
typedef void (*cbFxn)(CbData cbData);
/**
* \brief Structure containing callback data.
*/
struct CbData_t
{
uint32_t id;
/**< Id for which interrupt has occurred */
};
When I try to create doxygen (version 1.8.13), I get the below error:
warning: explicit link request to 'CbData' could not be resolved
How can I resolve this error?
Good day all, I'd like some help to change a small section in this C program which I have licensed back in the early 90's. Some of you may be familiar with it, it's called MajorBBS and as you probably have guess it is bbs software.
In the header file majorbbs.h we have
extern
struct module { /* module interface block */
char descrp[MNMSIZ]; /* description for main menu */
int (*lonrou)(); /* user logon supplemental routine */
int (*sttrou)(); /* input routine if selected */
void (*stsrou)(); /* status-input routine if selected */
int (*injrou)(); /* "injoth" routine for this module */
int (*lofrou)(); /* user logoff supplemental routine */
void (*huprou)(); /* hangup (lost carrier) routine */
void (*mcurou)(); /* midnight cleanup routine */
void (*dlarou)(); /* delete-account routine */
void (*finrou)(); /* finish-up (sys shutdown) routine */
} **module;
Also in the majorbbs.h we have some code that defines the menu variables
extern
struct usrmnu { /* user's menuing-specific variables */
char curpag[PNMSIZ]; /* current menu page */
char parpag[PNMSIZ]; /* parent menu page */
char selchrs[MAXSEL]; /* select characters currently available */
char pages[MAXSEL][PNMSIZ]; /* pages or file names for select chars */
char optdsp[MAXSEL]; /* instructions on how to display options */
int keyreq[MAXSEL]; /* key required for each select character */
FILE *fp; /* pointer to file currently being viewed */
char mnuttl[TITLSZ]; /* menu page title */
} *mnuusr;
Then in the majorbbs.c file we have
struct module module00={ /* module interface block */
"Menuing System", /* description for main menu */
NULL, /* user logon supplemental routine */
mainu, /* input routine if selected */
musthn, /* status-input routine if selected */
NULL, /* "injoth" routine for this module */
NULL, /* user logoff supplemental routine */
loscar, /* hangup (lost carrier) routine */
midnit, /* midnight cleanup routine */
NULL, /* delete-account routine */
mjrfin /* finish-up (sys shutdown) routine */
};
What I'd like is to change the value of the descrp here which is defined as "Menuing System" to something more dynamic like the Menu the user is currently on.
From the code here I think it would be mnuusr->curpag which is where the pointer is pointing to I think.
So I'm thinking of a routine. I am by no means a programmer and I've been there many sites to look for examples of how to do such a thing. I've searched here for the last couple days (before posting this). I saw some things
that sparked a "Hey this might work" but I ended up with compiler errors (more on that in a bit)
What I did was make a routine like
char *
mydescrp
{
if (strcmp(module00.descrp,"Menuing System" ) == 0 ) {
mnuusr=mnuoff(usrnum);
return(mnuusr->mnuttl);
}
}
Then if I change the module00 call above to
struct module module00={
mydescrp, /* My change */
NULL,
mainu,
musthn,
NULL,
NULL,
loscar,
midnit,
NULL,
mjrfin
};
When I compile I get some error that says:
Initalization not fully bracketed
the list goes on from there. There are some further initialization later on in majorbbs.c and will gladly supply them if you need. I am sure one would be.
int
register_module( /* register a module for online use */
struct module *mod) /* pointer to a module block */
{
if (strlen(mod->descrp) > MNMSIZ-1) {
catastro("MODULE NAME \"%s\" TOO LONG!",mod->descrp);
}
if (mod->stsrou == NULL) {
mod->stsrou=dfsthn;
}
if (nmods == 0) {
module=(struct module **)alcmem(sizeof(struct module *));
mdstats=(struct mdstats *)alcmem(sizeof(struct mdstats));
}
else {
module=(struct module **)alcrsz(module,sizeof(struct module *)*nmods,
sizeof(struct module *)*(nmods+1));
mdstats=(struct mdstats *)alcrsz(mdstats,sizeof(struct mdstats)*nmods,
sizeof(struct mdstats)*(nmods+1));
}
module[nmods]=mod;
setbtv(mstbb);
if (qeqbtv(mod->descrp,0)) {
gcrbtv(&mdstats[nmods],0);
}
else {
setmem(&mdstats[nmods],sizeof(struct mdstats),0);
strcpy(mdstats[nmods].mdname,mod->descrp);
}
rstbtv();
return(nmods++);
}
From MENUING.C mnuoff routine
struct usrmnu *
mnuoff( /* get pointer to user's menu info */
int unum) /* user number to grab */
{
#ifdef PHARLAP
return((struct usrmnu *)((long)(eclmnubas+(unum<<3))<<16));
#else
#ifdef ECLIPSE
return((struct usrmnu *)((long)(eclmnubas+(unum<<3))<<16));
#else
return((struct usrmnu *)(muusrs+(unum*(long)sizeof(struct usrmnu))));
#endif
#endif
}
Is this the routine to change for some newly code? I am simply at a loss on how to go about this. If you need more code let me know.
I even went as far as asking for help from other majorbbs programmers on usenet but this software is 20 years + old so I don't think anyone uses it anymore let alone modify code anymore. I would think since it's still C someone might have an idea to help me out. I am trying to create a new revive with some small modifications. This being one of two.
Thanks for any help.
It looks like the descrp field in struct module is expecting a char[] (or a string), and you're giving it a char *() (function returning a string) instead.
Perhaps what you want to do is not call the mydescrp function in the declaration of module00, but manually perform the check in register_module:
int register_module(struct module *mod) {
if (strcmp(mod->descrp, "Menuing System") == 0) {
struct usrmnu *menu = mnuoff(usrnum);
// Copy as much of the title to the menu description as possible.
strncpy(mod->descrp, menu->mnuttl, MNMSIZ-1);
// Terminate the string in case the title was too long.
mod->descrp[MNMSIZ-1] = '\0';
}
// Rest of method.
}
In the function
static int sqlite3Prepare(
sqlite3 *db, /* Database handle. */
const char *zSql, /* UTF-8 encoded SQL statement. */
int nBytes, /* Length of zSql in bytes. */
int saveSqlFlag, /* True to copy SQL text into the sqlite3_stmt */
Vdbe *pReprepare, /* VM being reprepared */
sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
const char **pzTail /* OUT: End of parsed string */
) {
...
pParse = sqlite3StackAllocZero(db, sizeof(*pParse));
...
assert( !db->mallocFailed );
...
}
I know sqlite3 is just a fake struct declared as
typedef struct sqlite3 sqlite3;
without any body. I know sqlite3 * is usually is cast to a Vdbe*.
But here, db is of the type of sqlite3*, how can db->malloFailed exist? Why doesn't the compiler complain?
There is similar situation with sqlite3_stmt:
typedef struct sqlite3_stmt sqlite3_stmt;
with no body. I guess sqlite3_stmt is a syntax tree of parsed SQL statements. I would like to see the structure of it. However, the type is hidden so deeply using this weird pattern that I can't see what it is.
Even Vdbe is the same situation...
typedef struct Vdbe Vdbe;
Where on earth is the real struct?
sqlite3 is not a fake struct; the sqlite.h file just does not define its body.
Its definition is in the sqliteInt.h file (which is also part of the sqlite3.c amalgamation):
/*
** Each database connection is an instance of the following structure.
*/
struct sqlite3 {
sqlite3_vfs *pVfs; /* OS Interface */
struct Vdbe *pVdbe; /* List of active virtual machines */
CollSeq *pDfltColl; /* The default collating sequence (BINARY) */
...
u8 mallocFailed; /* True if we have seen a malloc failure */
...
I am trying to convert a win32 application in to service. I use CreateService() to create it application as a service(using below code).
SC_HANDLE schService = CreateService
(
schSCManager, /* SCManager database */
pName, /* name of service */
pName, /* service name to display */
SERVICE_ALL_ACCESS, /* desired access */
SERVICE_WIN32_OWN_PROCESS|SERVICE_INTERACTIVE_PROCESS , /*service type*/
SERVICE_AUTO_START, /* start type */
SERVICE_ERROR_NORMAL, /* error control type */
pPath, /* service's binary */
NULL, /* no load ordering group */
NULL, /* no tag identifier */
NULL, /* no dependencies */
NULL, /* LocalSystem account */
NULL
); /* no password */
I am able to start the service, if there is no argument in the actual application. If i try to start the service with argument, then its creating problem.
LPCTSTR apszSvcArgv[32] = {"start","passwd"};
int nSvcArgc = 2;
if(StartService(schService, nSvcArgc,apszSvcArgv))
{
return TRUE;
}
I tried to dump the incoming argument in the main program and its always showing the no of argument as 1.
Am i doing anything wrong?. Is it possible to pass argument like this to a win32 console application.
Please correct me if i am wrong.. Thanks in advance
you need to define the args vector as const char (or wchar), then pass the vector to StartService.
here is an example for a unicode program in VS
const wchar_t *args[] = { L"arg1", L"arg2", L"arg3", L"arg4" };
StartService(schService, 4, args);