用C實現動態結構機制

大型C工程中存在模塊與模塊之間傳遞結構體的編譯一致性問題,由於C是靜態語言,編譯後結構體成員都固化爲地址偏移量,當結構體定義變更後必須保證相關模塊全編譯,不然會破壞進程棧且程序沒法主動發現。

InterBankPlus交易管理層精心設計了動態結構DS機制,解決了全編譯問題,並作了大量使用細節封裝,使得使用盡量方便。

調用者模塊先DS_NEW一個動態結構DS,DS_ADD輸入變量、變量類型、值,而後調用被調用者模塊入口函數,被調用者模塊從動態結構中DS_GET出變量,處理後DS_SET回動態結構,返回調用者模塊,調用者模塊DS_GET輸出變量,最後DS_DELETE動態結構。

模塊內部仍是建議使用靜態結構體,由於內部通常都是編譯一致的。

經過動態結構DS機制,模塊之間能夠安全的傳遞數據,至多也可被程序主動發現報錯,不至於被動的形成進程異常。

小技術解決大問題。git

#include "ibtm_in.h"

struct DS_infunc
{
	char	ch ;
	short	s ;
	int	i ;
	long	l ;
	float	f ;
	double	d ;
	char	buf[ 64 + 1 ] ;
} ;

int test_DS_infunc( DS *ds )
{
	struct DS_infunc	infunc ;
	
	DS_TRY(ds)
	{
		DS_GET( ds , char , char_field , & (infunc.ch) )
		DS_GET( ds , short , short_field , & (infunc.s) )
		DS_GET( ds , int , int_field , & (infunc.i) )
		DS_GET( ds , long , long_field , & (infunc.l) )
		DS_GET( ds , float , float_field , & (infunc.f) )
		DS_GET( ds , double , double_field , & (infunc.d) )
		DS_GET( ds , char* , string_field , infunc.buf , sizeof(infunc.buf) )
	}
	DS_CATCH(ds)
	{
		printf( "DS_GET failed , LINE[%d] FIELD_NAME[%s] ERROR[%d]\n" , DSGetLastSourceLine(ds) , DSGetFieldName(ds) , DSGetLastError(ds) );
		return -1;
	}
	
	printf( "--- infunc ---\n" );
	printf( "infunc.ch [%c]\n" , infunc.ch );
	printf( "infunc.s  [%hd]\n" , infunc.s );
	printf( "infunc.i  [%d]\n" , infunc.i );
	printf( "infunc.l  [%ld]\n" , infunc.l );
	printf( "infunc.f  [%f]\n" , infunc.f );
	printf( "infunc.d  [%lf]\n" , infunc.d );
	printf( "infunc.buf[%s]\n" , infunc.buf );
	
	DS_TRY(ds)
	{
		DS_SET( ds , char , char_field , 'Z' )
		DS_SET( ds , short , short_field , 9 )
		DS_SET( ds , int , int_field , 87 )
		DS_SET( ds , long , long_field , 654321 )
		DS_SET( ds , float , float_field , 9.8 )
		DS_SET( ds , double , double_field , 7654.3210 )
		DS_SET( ds , char* , string_field , "world" )
	}
	DS_CATCH(ds)
	{
		printf( "DS_SET failed , LINE[%d] FIELD_NAME[%s] ERROR[%d]\n" , DSGetLastSourceLine(ds) , DSGetFieldName(ds) , DSGetLastError(ds) );
		return -1;
	}
	
	return 0;
}

struct DS_caller
{
	char	ch ;
	short	s ;
	int	i ;
	long	l ;
	float	f ;
	double	d ;
	char	buf[ 64 + 1 ] ;
} ;

int test_DS_caller()
{
	struct DS_caller	caller ;
	DS			*ds = DS_NEW( "struct_name" ) ;
	
	if( ds == NULL )
	{
		printf( "DS_NEW failed , errno[%d]\n" , errno );
		return -1;
	}
	
	memset( & caller , 0x00 , sizeof(struct DS_caller) );
	caller.ch = 'A' ;
	caller.s = 1 ;
	caller.i = 23 ;
	caller.l = 456789 ;
	caller.f = 1.2 ;
	caller.d = 3456.7890 ;
	strcpy( caller.buf , "hello" );
	
	DS_TRY(ds)
	{
		DS_ADD( ds , char , char_field , caller.ch )
		DS_ADD( ds , short , short_field , caller.s )
		DS_ADD( ds , int , int_field , caller.i )
		DS_ADD( ds , long , long_field , caller.l )
		DS_ADD( ds , float , float_field , caller.f )
		DS_ADD( ds , double , double_field , caller.d )
		DS_ADD( ds , char* , string_field , caller.buf )
	}
	DS_CATCH(ds)
	{
		printf( "DS_ADD failed , LINE[%d] FIELD_NAME[%s] ERROR[%d]\n" , DSGetLastSourceLine(ds) , DSGetFieldName(ds) , DSGetLastError(ds) );
		DS_DELETE( ds )
		return -1;
	}
	
	test_DS_infunc( ds );
	
	memset( & caller , 0x00 , sizeof(struct DS_caller) );
	
	DS_TRY(ds)
	{
		DS_GET( ds , char , char_field , & (caller.ch) )
		DS_GET( ds , short , short_field , & (caller.s) )
		DS_GET( ds , int , int_field , & (caller.i) )
		DS_GET( ds , long , long_field , & (caller.l) )
		DS_GET( ds , float , float_field , & (caller.f) )
		DS_GET( ds , double , double_field , & (caller.d) )
		DS_GET( ds , char* , string_field , caller.buf , sizeof(caller.buf) )
	}
	DS_CATCH(ds)
	{
		printf( "DS_GET failed , LINE[%d] FIELD_NAME[%s] ERROR[%d]\n" , DSGetLastSourceLine(ds) , DSGetFieldName(ds) , DSGetLastError(ds) );
		DS_DELETE( ds )
		return -1;
	}
	
	printf( "--- caller ---\n" );
	printf( "caller.ch [%c]\n" , caller.ch );
	printf( "caller.s  [%hd]\n" , caller.s );
	printf( "caller.i  [%d]\n" , caller.i );
	printf( "caller.l  [%ld]\n" , caller.l );
	printf( "caller.f  [%f]\n" , caller.f );
	printf( "caller.d  [%lf]\n" , caller.d );
	printf( "caller.buf[%s]\n" , caller.buf );
	
	DS_DELETE( ds )
	
	return 0;
}

int main()
{
	return -test_DS_caller();
}
相關文章
相關標籤/搜索