应用背景 canopen 协议栈中 ,对object dictionary 的回调函数, 通过指针函数数组的方式进行保存,
但这种保存方式有一个问题 就可能会浪费空间 。
所以这里采用链表方式存储回调函数 ,当然 必须额外空间存储链表操作的代码 。
工程是在Eclipse IDE for C/C++ Developers平台上 用c语言编写的 ,对于理解c语言指针应用有一定的帮助 。
原创文章,不得用于商业目的。
/*
* user.h*
* Created on: 2018年6月30日
* Author: gx fleetwgx fleetwgx@163.com
*/
#ifndef USER_H_
#define USER_H_
#define bool unsigned char
#define null 0
#define true 1
#define false (!true)
#endif /* USER_H_ */
/*
* linklist.h
*
* Created on: 2018年6月30日
* Author: gx fleetwgx fleetwgx@163.com
*/
#ifndef LINKLIST_H_
#define LINKLIST_H_
#include <stdio.h>
#include <stdlib.h>
#include "user.h"
#define LLIST_HEAD_INSERT 0x00
#define LLIST_TAIL_INSERT 0x01
typedef struct LListNode
{
void*pElement;
struct LListNode *pNext;
}LListNode_t;
typedef struct LListNode* PLListNode;
/*
typedef struct LListHead
{
unsigned char nodeNum;
struct LListNode firstNode;
}LListHead_t;
*/
typedef bool (*NodeElementCmpFun)(void *pElementa ,void *pElemntb);
typedef void (*printElementFun)(void *pElement);
extern void initLList( LListNode_t**pNode );
extern LListNode_t *createLList( LListNode_t*pHead );
extern void clearLList( LListNode_t*pHead );
extern bool isEmptyLList( LListNode_t*pHead );
extern void* getLListElement( LListNode_t**pHead , void* pElement ,NodeElementCmpFun elementCmpCallBack );
extern int insertLList( LListNode_t**pHead , unsigned char type , void * pElement );
extern int modifyLList( LListNode_t*pHead , unsigned int key );
extern void printLList( LListNode_t*pHead ,printElementFun printCallback);
#endif /* LINKLIST_H_ */
/*
* linklist.c
*
* Created on: 2018年6月30日
* Author: gx fleetwgx fleetwgx@163.com
*/
#include "linklist.h"
void initLList( LListNode_t**pNode )
{
*pNode = null;
}
LListNode_t *createLList( LListNode_t*pHead )
{
return null;
}
void clearLList( LListNode_t*pHead )
{
}
bool isEmptyLList( LListNode_t*pHead )
{
if(pHead == null){
return true;
}else{
return false;
}
}
void* getLListElement( LListNode_t**pHead , void *pElement , NodeElementCmpFun elementCmpCallBack )
{
//unsigned int i;
LListNode_t*pNode = *pHead;
if( (*pHead==null) ||(pElement== null)){
return pNode;
}
while( pNode!=null ){
if( ( pNode->pElement!=null )/*&&(pElement!=null)*/&&(true == elementCmpCallBack( pNode->pElement , pElement) ) ){
printf(" getLListElement result is the element in this LList!\n");
break;
}else{
pNode = pNode->pNext;
}
}
return pNode;
}
int insertLList( LListNode_t **pHead , unsigned char type , void * pElement )
{
struct LListNode* pNewNode;
if( ( pElement == null ) || (type > LLIST_TAIL_INSERT) ){
return false;
}
if( *pHead == null ){
pNewNode = malloc(sizeof(struct LListNode));
if(pNewNode!=null){
pNewNode->pElement = pElement;
pNewNode->pNext = null;
*pHead = pNewNode;
}
}
else if( type == LLIST_HEAD_INSERT ){
pNewNode = (struct LListNode*)malloc( sizeof(struct LListNode) );
if(pNewNode!=null){
pNewNode->pElement = pElement;
pNewNode->pNext = (*pHead)->pNext;
(*pHead)->pNext = pNewNode;
}
}else {
;//
}
return true;
}
int modifyLList( LListNode_t*pHead , unsigned int key )
{
return 0;
}
void printLList( LListNode_t*pHead ,printElementFun printCallback)
{
LListNode_t *pNode;
if(pHead==null){
printf("the input LList is a null list!\n");
}else{
pNode = pHead;
printf("--------printLList------------\n");
while(pNode!=null){
printf("the current LListNode element is:\n");
printCallback(pNode->pElement);
pNode = pNode->pNext;
printf("\n");
}
printf("------------end--------------\n");
}
}
/*
* odjacess.h
*
* Created on: 2018年6月30日
* Author: gx fleetwgx fleetwgx@163.com
*/
#ifndef ODJACESS_H_
#define ODJACESS_H_
#include <stdio.h>
#include <stdlib.h>
#include "user.h"
#include "linklist.h"
//#define null 0
#define OD_SUCCESSFUL 0x00000000
#define OD_READ_NOT_ALLOWED 0x06010001
#define OD_WRITE_NOT_ALLOWED 0x06010002
#define OD_NO_SUCH_OBJECT 0x06020000
#define OD_NOT_MAPPABLE 0x06040041
#define OD_LENGTH_DATA_INVALID 0x06070010
#define OD_NO_SUCH_SUBINDEX 0x06090011
#define OD_VALUE_TOO_LOW 0x06090031 /* Value range test result */
#define OD_VALUE_TOO_HIGH 0x06090032 /* Value range test result */
#define OD_CALLBACK_NOTSUPPORT 0x06090033 /* add by user*/
/* Others SDO abort codes
*/
#define SDOABT_TOGGLE_NOT_ALTERNED 0x05030000
#define SDOABT_TIMED_OUT 0x05040000
#define SDOABT_OUT_OF_MEMORY 0x05040005 /* Size data exceed SDO_MAX_LENGTH_TRANSFERT */
#define SDOABT_GENERAL_ERROR 0x08000000 /* Error size of SDO message */
#define SDOABT_LOCAL_CTRL_ERROR 0x08000021
typedef struct Co_Handle;
typedef struct Co_OdHandle;
typedef struct td_subindex
{
unsigned char bAccessType;
unsigned char bDataType; /* Defines of what datatype the entry is */
unsigned char size; /* The size (in Byte) of the variable */
void* pObject; /* This is the pointer of the Variable */
} subindex;
/** Struct for creating entries in the communictaion profile
*/
typedef struct td_indextable
{
subindex* pSubindex; /* Pointer to the subindex */
unsigned char bSubCount; /* the count of valid entries for this subindex
* This count here defines how many memory has been
* allocated. this memory does not have to be used.
*/
unsigned char index;
} indextable;
typedef unsigned int ( *ODCallBack_t )( struct Co_Handle *pHandle , struct td_indextable* pIndexTable , unsigned char subIndex );
typedef const indextable * (*scanIndexOD_t)( struct Co_OdHandle* pHandle, unsigned short index, unsigned int * errorCode, void **Callback);
typedef struct Co_entrysubIndexCallBack
{
unsigned char subIndex;
ODCallBack_t callBack;
}Co_entrysubIndexCallBack_t;
typedef struct Co_entryCallBacks
{
unsigned short index ;
unsigned char subIndexNum;
//struct Co_entrysubIndexCallBack* pCallBackList;//0x20//every index max 20 callback functions
#if 1
struct LListNode* pCallBackList;//head
#else
PLListNode pCallBackList; //
#endif
}Co_entryCallBacks_t;
typedef struct Co_OdHandle
{
unsigned int initFlag;
scanIndexOD_t scanIndexOD;
scanIndexOD_t getIndexCallbackList;
NodeElementCmpFun callbackCmp;
printElementFun callBackPrint;
//struct Co_entryCallBacks*pOdEntryCallBacks;
}Co_OdHandle_t;
typedef struct Co_Handle
{
struct Co_OdHandle*pOdHandle;
}Co_Handle_t;
extern void Co_Init(struct Co_Handle* pHandle ,scanIndexOD_t scanIndeOdFun , unsigned char CallbackFunctionNum , unsigned short*pCallbackFunctionTables );
extern struct indextable * scanIndexODFun ( struct Co_OdHandle* pHandle, unsigned short index, unsigned int * errorCode, struct LListNode** pCallBackList /*ODCallBack_t **Callback*/);
//extern struct indextable * scanIndexODFun ( struct Co_OdHandle* pHandle, unsigned short index, unsigned int * errorCode, struct LListNode** pCallBackList /*ODCallBack_t **Callback*/)
//;
//extern struct indextable * scanIndexODFun (unsigned short index, unsigned int * errorCode, struct LListNode* pCallBackList /*ODCallBack_t **Callback*/ );
#endif /* ODJACESS_H_ */
/*
* odjacess.c
*
* Created on: 2018年6月30日
* Author: gx fleetwgx fleetwgx@163.com
*/
#include "odjacess.h"
#include "linklist.h"
//struct Co_entryCallBacks OdEntryCallBacks[0x20];//0x20 *0x20 callback matrix
struct Co_entryCallBacks*pOdEntryCallBacks;
struct indextable * scanIndexODFun ( struct Co_OdHandle* pHandle, unsigned short index, unsigned int * errorCode, struct LListNode** pCallBackList /*ODCallBack_t **Callback*/)
{
unsigned int i;
printf(" objaccess -> call scanIndexODFun\n");
*errorCode = OD_CALLBACK_NOTSUPPORT;//
for(i = 0 ; i < 0x20 ; i++ ){
//if(index == pHandle->pOdEntryCallBacks[i].index ){
if( index == pOdEntryCallBacks[i].index){
*pCallBackList = (struct LListNode*) (&(pOdEntryCallBacks[i].pCallBackList));
*errorCode = OD_SUCCESSFUL;
break;
}
}
return null;
}
bool SubIndexcallBackFunCmp( void*callBacka , void*callBackb )
{
if( ((struct Co_entrysubIndexCallBack*)callBacka)->subIndex ==\
((struct Co_entrysubIndexCallBack*)callBackb)->subIndex ){
return true;
}else{
return false;
}
//
}
void SubIndexcallBackFunPrint( void*pElement )
{
if( pElement!=null ){
printf("the subindex is : %d \n" , ( (struct Co_entrysubIndexCallBack *)pElement)->subIndex );
}else{
printf("pElement is null\n");
}
}
void SubIndexcallBackFunPrint2( struct Co_Handle* pHandle, LListNode_t*pHead )
{
LListNode_t*pNode;
pNode = pHead;
unsigned char subIndex;
while(pNode!=null){
if(pNode->pElement!=null){
subIndex = ((struct Co_entrysubIndexCallBack*)(pNode->pElement))->subIndex;
((struct Co_entrysubIndexCallBack*)(pNode->pElement))->callBack(pHandle,null,subIndex);
}
pNode = pNode->pNext;
}
}
//list tables
void Co_Init(struct Co_Handle* pHandle ,scanIndexOD_t scanIndeOdFun , unsigned char CallbackFunctionNum , unsigned short*pCallbackFunctionTables )
{
unsigned int i;
// unsigned char CallbackFunctionSize[][];
struct Co_entryCallBacks temp;//debug
pHandle->pOdHandle = malloc(sizeof(Co_OdHandle_t) );
if( (pHandle->pOdHandle!=null) && (scanIndeOdFun!=null) ){
//(*pHandle->pOdHandle).scanIndexOD = scanIndeOdFun;
(*pHandle->pOdHandle).getIndexCallbackList = scanIndeOdFun;
(*pHandle->pOdHandle).initFlag = 0x55AA; //
(*pHandle->pOdHandle).callbackCmp = SubIndexcallBackFunCmp;
(*pHandle->pOdHandle).callBackPrint = SubIndexcallBackFunPrint;
pOdEntryCallBacks = malloc(CallbackFunctionNum*sizeof(Co_entryCallBacks_t) );
if( pOdEntryCallBacks !=null){
for( i = 0 ; i < CallbackFunctionNum ; i++){
pOdEntryCallBacks[i].index = pCallbackFunctionTables[i];
pOdEntryCallBacks[i].subIndexNum = 0;
initLList(&pOdEntryCallBacks[i].pCallBackList); //a simple method, consider *p as a normal variable,
temp = pOdEntryCallBacks[i];
}
}
/*
pHandle->pOdHandle->pOdEntryCallBacks = malloc(CallbackFunctionNum*sizeof(Co_entryCallBacks_t) );
if( pHandle->pOdHandle->pOdEntryCallBacks !=null){
for( i = 0 ; i < CallbackFunctionNum ; i++){
pHandle->pOdHandle->pOdEntryCallBacks[i].index = pCallbackFunctionTables[i];
}
}
*/
//
}else{
(*pHandle->pOdHandle).scanIndexOD = null;
(*pHandle->pOdHandle).initFlag = 0x0000; //
}
//
}
struct Co_OdHandle* Co_getOdHandle(struct Co_Handle* pHandle)
{
if(pHandle!=null){
return pHandle->pOdHandle;
}else{
return null;
}
}
indextable * scanIndexOD( struct Co_OdHandle* pOdHandle, unsigned short index, unsigned int * errorCode, ODCallBack_t **Callback )
{
if( ( pOdHandle!=null) && ( pOdHandle->scanIndexOD!=null ) ){
return pOdHandle->scanIndexOD( pOdHandle , index , errorCode , Callback );
}else{
return null;
}
}
indextable * getIndexCallbackList( struct Co_OdHandle* pOdHandle , unsigned short index , unsigned int * errorCode, struct LListNode **pCallBackListHead )
{
if( ( pOdHandle!=null) && ( pOdHandle->getIndexCallbackList!=null ) ){
return pOdHandle->getIndexCallbackList( pOdHandle , index , errorCode , pCallBackListHead );
}else{
return null;
}
}
#if 1
bool getIndexCallBackListHead( struct Co_OdHandle* pOdHandle , unsigned short index , struct LListNode **pCallBackListHead)//
#else
bool getIndexCallBackListHead( struct Co_OdHandle* pOdHandle , unsigned short index , PLListNode *pCallBackListHead)
#endif
{
unsigned int errCode;
getIndexCallbackList(pOdHandle , index , &errCode, pCallBackListHead);
if(errCode == OD_SUCCESSFUL)
return true;
else
return false;
}
void printIndexCallBackList( struct Co_OdHandle *pOdHandle , LListNode_t**pHead)
{
if( (pOdHandle!=null)&&(pHead!=null) )
printLList(*pHead , pOdHandle->callBackPrint );
}
struct Co_entrysubIndexCallBack * createSubIndexCallBackNode(unsigned char subIndex , ODCallBack_t callBack )
{
struct Co_entrysubIndexCallBack *pCallBackNodeElement = null;
pCallBackNodeElement = malloc( sizeof( struct Co_entrysubIndexCallBack ) );//
if(pCallBackNodeElement!=null){
pCallBackNodeElement->callBack = callBack; //
pCallBackNodeElement->subIndex = subIndex; //
return pCallBackNodeElement;
}else{
return null;
}
}
bool deleteSubIndexCallBackNode( struct Co_entrysubIndexCallBack * pNode )
{
if( pNode!=null ){
free(pNode);
return true;
}else{
return false;
}
}
bool setSubIndexCallBackNode( struct Co_entrysubIndexCallBack *pNode , ODCallBack_t callBack )//
{
if(pNode!=null){
pNode->callBack = callBack;
return true;
}else{
return false;
}
}
struct Co_entrysubIndexCallBack * getSubIndexCallBackNode( struct Co_OdHandle *pOdHandle , LListNode_t**pHead , unsigned char subIndex)
{
struct LListNode *pNode;
struct Co_entrysubIndexCallBack CallBackNodeElement;
CallBackNodeElement.subIndex = subIndex;
pNode = getLListElement( pHead , &CallBackNodeElement , pOdHandle->callbackCmp );
if(pNode!=null){
return (struct Co_entrysubIndexCallBack *)pNode->pElement;
}
return null;
}
bool addSubIndexCallBackNodeToIndexCallBackList(LListNode_t**pHead,struct Co_entrysubIndexCallBack *pCallBackNodeElement)
{
if( (pHead != null ) &&( pCallBackNodeElement != null ) ){
return insertLList( pHead , LLIST_HEAD_INSERT , pCallBackNodeElement) ;
}else{
return false;
}
}
bool removeSubIndexCallBackNodeToIndexCallBackList(LListNode_t*pHead ,unsigned char subIndex)
{
return false;
}
unsigned int RegisterODCallBack( struct Co_Handle *pHandle , unsigned short index ,unsigned char subIndex , ODCallBack_t callBack)//
{
unsigned int errCode;
struct Co_OdHandle *pOdHandle = pHandle->pOdHandle;
#if 1
struct LListNode **pCallBackListHead = null;
#else
PLListNode *pCallBackListHead = null;
#endif
struct Co_entrysubIndexCallBack *pCallBackNodeElement = null;
if( true == getIndexCallBackListHead (pOdHandle , index , &pCallBackListHead) ){
/*why here use &pCallBackListHead?
* int a; fun(int*a) fun(&a);
* int**a; fun(int**a) fun(&a);
*
* */
//
pCallBackNodeElement = getSubIndexCallBackNode(pOdHandle,pCallBackListHead,subIndex);
if( pCallBackNodeElement!=null ){
setSubIndexCallBackNode( pCallBackNodeElement , callBack);
}else{
pCallBackNodeElement = createSubIndexCallBackNode( subIndex , callBack );//
errCode = OD_SUCCESSFUL;
if( (pCallBackNodeElement!=null)&&
(false == addSubIndexCallBackNodeToIndexCallBackList( pCallBackListHead ,pCallBackNodeElement )) ){
deleteSubIndexCallBackNode(pCallBackNodeElement);
errCode = ~OD_SUCCESSFUL;
}
printIndexCallBackList(pOdHandle,pCallBackListHead);
}
}
return errCode;
}
/*
============================================================================
Name : test2.c
Author : guixin fleetwgx fleetwgx@163.com
Version :
Copyright : Your copyright notice
Description : Hello World in C, Ansi-style
============================================================================
*/
#include <stdio.h>
#include <stdlib.h>
#include "odjacess.h"
static unsigned int OnCob_Id_SyncUpdate(struct Co_Handle *pHandle , struct td_indextable* pIndexTable , unsigned char subIndex )
{
printf(" test2 -> call OnCob_Id_SyncUpdate\n,subindex = %x\n",subIndex);
startSync(pHandle);
return 0;
}
void startSync( struct Co_Handle *pHandle)
{
printf(" test2 -> call startSync \n");
RegisterODCallBack( pHandle , 0x1005 ,0x0 , OnCob_Id_SyncUpdate );//
RegisterODCallBack( pHandle , 0x1006 ,0x0 , OnCob_Id_SyncUpdate );//
RegisterODCallBack( pHandle , 0x1005 ,0x0 , OnCob_Id_SyncUpdate );//only for debug
RegisterODCallBack( pHandle , 0x1006 ,0x0 , OnCob_Id_SyncUpdate );//only for debug
RegisterODCallBack( pHandle , 0x1005 ,0x1 , OnCob_Id_SyncUpdate );//only for debug
RegisterODCallBack( pHandle , 0x1005 ,0x2 , OnCob_Id_SyncUpdate );//only for debug
RegisterODCallBack( pHandle , 0x1005 ,0x3 , OnCob_Id_SyncUpdate );//only for debug
RegisterODCallBack( pHandle , 0x1005 ,0x4 , OnCob_Id_SyncUpdate );//only for debug
//
}
struct Co_Handle coHandle;
unsigned short oDCallBackMatrixs[]=
{
0x1005,
0x1006,
0x1007,
0x1008,
0x1009,
0x100a
};
int main(void) {
puts("!!!Hello World!!!18-7-7\n"); /* prints !!!Hello World!!! */
Co_Init( &coHandle , scanIndexODFun , sizeof(oDCallBackMatrixs)/2 , &oDCallBackMatrixs ); //
startSync(&coHandle); //
struct LListNode **pCallBackListHead = null;
unsigned int errCode;
struct Co_OdHandle* pOdHandle;
pOdHandle = Co_getOdHandle();
puts("debug continue....\n");
if( ( pOdHandle!=null)/* && ( coHandle.pOdHandle->scanIndexOD!=null )*/ ){
if(true == getIndexCallBackListHead( pOdHandle , 0x1005 , &pCallBackListHead)){
SubIndexcallBackFunPrint2( &coHandle, *pCallBackListHead );
}
if(true == getIndexCallBackListHead( pOdHandle , 0x1006 , &pCallBackListHead)){
SubIndexcallBackFunPrint2( &coHandle, *pCallBackListHead );
}
}
return EXIT_SUCCESS;
}