From 9656cc01db1d8f0f3d7cd727997b5f7a8956d126 Mon Sep 17 00:00:00 2001 From: Tom Levens Date: Thu, 4 Jun 2015 14:04:07 +0200 Subject: [PATCH 1/5] VXI11_CLIENTS is passed to open/close functons VXI11_CLIENTS is no longer a global variable but is instead passed to the open/close functions. In a multithreaded application the global variable causes problems. Instead it is up to the calling code to protect this variable. --- library/vxi11_user.c | 35 +++++++---------------------------- library/vxi11_user.h | 15 +++++++++++++-- 2 files changed, 20 insertions(+), 30 deletions(-) diff --git a/library/vxi11_user.c b/library/vxi11_user.c index 86df97d..9123886 100644 --- a/library/vxi11_user.c +++ b/library/vxi11_user.c @@ -72,27 +72,6 @@ struct _VXI11_CLINK { * double vxi11_obtain_double_value(VXI11_CLINK *clink, char *cmd, unsigned long timeout) */ -/* Global variables. Keep track of multiple links per client. We need this - * because: - * - we'd like the library to be able to cope with multiple links to a given - * client AND multiple links to multiple clients - * - we'd like to just refer to a client/link ("clink") as a single - * entity from user land, we don't want to worry about different - * initialisation procedures, depending on whether it's an instrument - * with the same address or not - */ - -struct _vxi11_client_t { - struct _vxi11_client_t *next; - char address[20]; -#ifndef WIN32 - CLIENT *client_address; -#endif - int link_count; -}; - -static struct _vxi11_client_t *VXI11_CLIENTS = NULL; - /* Internal function declarations. */ static int _vxi11_open_link(VXI11_CLINK * clink, const char *address, char *device); @@ -107,7 +86,7 @@ static int _vxi11_close_link(VXI11_CLINK * clink, const char *address); /* Use this function from user land to open a device and create a link. Can be * used multiple times for the same device (the library will keep track).*/ -int vxi11_open_device(VXI11_CLINK **clink, const char *address, char *device) +int vxi11_open_device(VXI11_CLINK **clink, const char *address, char *device, struct _vxi11_client_t **vxi11_clients) { #ifdef WIN32 ViStatus status; @@ -150,7 +129,7 @@ int vxi11_open_device(VXI11_CLINK **clink, const char *address, char *device) #else /* Have a look to see if we've already initialised an instrument with * this address */ - tail = VXI11_CLIENTS; + tail = *vxi11_clients; while (tail) { if (strcmp(address, tail->address) == 0) { client = tail; @@ -195,8 +174,8 @@ int vxi11_open_device(VXI11_CLINK **clink, const char *address, char *device) strncpy(client->address, address, 20); client->client_address = (*clink)->client; client->link_count = 1; - client->next = VXI11_CLIENTS; - VXI11_CLIENTS = client; + client->next = *vxi11_clients; + *vxi11_clients = client; } else { /* Copy the client pointer address. Just establish a new link * not a new client). Add one to the link count */ @@ -213,7 +192,7 @@ int vxi11_open_device(VXI11_CLINK **clink, const char *address, char *device) /* Use this function from user land to close a device and/or sever a link. Can * be used multiple times for the same device (the library will keep track).*/ -int vxi11_close_device(VXI11_CLINK * clink, const char *address) +int vxi11_close_device(VXI11_CLINK * clink, const char *address, struct _vxi11_client_t **vxi11_clients) { int ret = 0; #ifdef WIN32 @@ -223,7 +202,7 @@ int vxi11_close_device(VXI11_CLINK * clink, const char *address) struct _vxi11_client_t *tail, *last = NULL, *client = NULL; /* Which instrument are we referring to? */ - tail = VXI11_CLIENTS; + tail = *vxi11_clients; while (tail) { if (strncmp(address, tail->address, 20) == 0) { client = tail; @@ -254,7 +233,7 @@ int vxi11_close_device(VXI11_CLINK * clink, const char *address) if (last) { last->next = client->next; } else { - VXI11_CLIENTS = client->next; + *vxi11_clients = client->next; } } } diff --git a/library/vxi11_user.h b/library/vxi11_user.h index 4e7c3f4..98e67a8 100644 --- a/library/vxi11_user.h +++ b/library/vxi11_user.h @@ -41,6 +41,7 @@ extern "C" { #endif #include +#include typedef struct _VXI11_CLINK VXI11_CLINK; @@ -57,10 +58,20 @@ typedef struct _VXI11_CLINK VXI11_CLINK; /* vxi11_send() return value if a sent command times out ON THE INSTRUMENT. */ #define VXI11_NULL_WRITE_RESP 51 +/* client list stucture */ +struct _vxi11_client_t { + struct _vxi11_client_t *next; + char address[20]; +#ifndef WIN32 + CLIENT *client_address; +#endif + int link_count; +}; +typedef struct _vxi11_client_t vxi11_client_t; /* The four main functions: open, close, send, receieve (plus a couple of wrappers) */ -vx_EXPORT int vxi11_open_device(VXI11_CLINK **clink, const char *address, char *device); -vx_EXPORT int vxi11_close_device(VXI11_CLINK *clink, const char *address); +vx_EXPORT int vxi11_open_device(VXI11_CLINK **clink, const char *address, char *device, struct _vxi11_client_t **vxi11_clients); +vx_EXPORT int vxi11_close_device(VXI11_CLINK *clink, const char *address, struct _vxi11_client_t **vxi11_clients); vx_EXPORT int vxi11_send(VXI11_CLINK *clink, const char *cmd, size_t len); vx_EXPORT int vxi11_send_printf(VXI11_CLINK *clink, const char *format, ...); vx_EXPORT ssize_t vxi11_receive(VXI11_CLINK *clink, char *buffer, size_t len); From f9d04dc0848089f31e55179b196cba778ffb5814 Mon Sep 17 00:00:00 2001 From: Tom Levens Date: Fri, 31 Jul 2015 18:12:50 +0200 Subject: [PATCH 2/5] Fixed vxi11_user.h function prototype from merge --- library/vxi11_user.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/vxi11_user.h b/library/vxi11_user.h index b348ae0..87a055b 100644 --- a/library/vxi11_user.h +++ b/library/vxi11_user.h @@ -126,7 +126,7 @@ vx_EXPORT int vxi11_open_device(VXI11_CLINK **clink, const char *address, char * * Returns: * 0 - on success */ -vx_EXPORT int vxi11_close_device(VXI11_CLINK *clink, const char *address); +vx_EXPORT int vxi11_close_device(VXI11_CLINK *clink, const char *address, struct _vxi11_client_t **vxi11_clients); /* Function: vxi11_send From facf2c082a6ebd7745655ab3df0a85d015b44ee6 Mon Sep 17 00:00:00 2001 From: Tom Levens Date: Mon, 25 Jan 2016 03:56:28 +0100 Subject: [PATCH 3/5] Updated with new function names for compatibility vxi11_open_device() and vxi11_close_device() no longer have an argument for the clients, these functions again use a global variable. Two new functions are added, vxi11_open_device_clients() and vxi11_close_device_clients() to offer the option to pass an external clients list. --- .gitignore | 1 + library/linker.version | 2 ++ library/vxi11_user.c | 42 +++++++++++++++++++++++++++++--------- library/vxi11_user.h | 46 ++++++++++++++++++++++++++++++++++++------ 4 files changed, 75 insertions(+), 16 deletions(-) diff --git a/.gitignore b/.gitignore index 4fcd01f..53d5e2c 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ vxi11_send *.o *.pyc .pc/ +libvxi11.a diff --git a/library/linker.version b/library/linker.version index 3d9c829..b82bbf3 100644 --- a/library/linker.version +++ b/library/linker.version @@ -5,12 +5,14 @@ VXI11_2.0 { global: vxi11_close_device; + vxi11_close_device_clients; vxi11_lib_version; vxi11_obtain_double_value; vxi11_obtain_double_value_timeout; vxi11_obtain_long_value; vxi11_obtain_long_value_timeout; vxi11_open_device; + vxi11_open_device_clients; vxi11_receive; vxi11_receive_data_block; vxi11_receive_timeout; diff --git a/library/vxi11_user.c b/library/vxi11_user.c index 42948ab..046f899 100644 --- a/library/vxi11_user.c +++ b/library/vxi11_user.c @@ -53,6 +53,18 @@ struct _VXI11_CLINK { * GENERAL NOTES ***************************************************************************** + * Global variables. Keep track of multiple links per client. We need this + * because: + * - we'd like the library to be able to cope with multiple links to a given + * client AND multiple links to multiple clients + * - we'd like to just refer to a client/link ("clink") as a single + * entity from user land, we don't want to worry about different + * initialisation procedures, depending on whether it's an instrument + * with the same address or not + */ + +static vxi11_client_t *VXI11_CLIENTS = NULL; + /* Internal function declarations. */ static int _vxi11_open_link(VXI11_CLINK * clink, const char *address, char *device); @@ -77,14 +89,19 @@ int vxi11_lib_version(int *major, int *minor, int *revision) /* Use this function from user land to open a device and create a link. Can be * used multiple times for the same device (the library will keep track).*/ -int vxi11_open_device(VXI11_CLINK **clink, const char *address, char *device, struct _vxi11_client_t **vxi11_clients) +int vxi11_open_device(VXI11_CLINK **clink, const char *address, char *device) +{ + return vxi11_open_device_clients(clink, address, device, &VXI11_CLIENTS); +} + +int vxi11_open_device_clients(VXI11_CLINK **clink, const char *address, char *device, vxi11_client_t **clients) { #ifdef WIN32 ViStatus status; char buf[256]; #else int ret; - struct _vxi11_client_t *tail, *client = NULL; + vxi11_client_t *tail, *client = NULL; #endif char default_device[6] = "inst0"; char *use_device; @@ -120,7 +137,7 @@ int vxi11_open_device(VXI11_CLINK **clink, const char *address, char *device, st #else /* Have a look to see if we've already initialised an instrument with * this address */ - tail = *vxi11_clients; + tail = *clients; while (tail) { if (strcmp(address, tail->address) == 0) { client = tail; @@ -135,7 +152,7 @@ int vxi11_open_device(VXI11_CLINK **clink, const char *address, char *device, st * is, for this address. Because it's a new client, this * must be link number 1. Keep track of how many devices we've * opened so we don't run out of storage space. */ - client = (struct _vxi11_client_t *)calloc(1, sizeof(struct _vxi11_client_t)); + client = (vxi11_client_t *)calloc(1, sizeof(vxi11_client_t)); if (!client) { free(*clink); *clink = NULL; @@ -165,8 +182,8 @@ int vxi11_open_device(VXI11_CLINK **clink, const char *address, char *device, st strncpy(client->address, address, 20); client->client_address = (*clink)->client; client->link_count = 1; - client->next = *vxi11_clients; - *vxi11_clients = client; + client->next = *clients; + *clients = client; } else { /* Copy the client pointer address. Just establish a new link * not a new client). Add one to the link count */ @@ -183,17 +200,22 @@ int vxi11_open_device(VXI11_CLINK **clink, const char *address, char *device, st /* Use this function from user land to close a device and/or sever a link. Can * be used multiple times for the same device (the library will keep track).*/ -int vxi11_close_device(VXI11_CLINK * clink, const char *address, struct _vxi11_client_t **vxi11_clients) +int vxi11_close_device(VXI11_CLINK * clink, const char *address) +{ + return vxi11_close_device_clients(clink, address, &VXI11_CLIENTS); +} + +int vxi11_close_device_clients(VXI11_CLINK * clink, const char *address, vxi11_client_t **clients) { int ret = 0; #ifdef WIN32 viClose(clink->session); viClose(clink->rm); #else - struct _vxi11_client_t *tail, *last = NULL, *client = NULL; + vxi11_client_t *tail, *last = NULL, *client = NULL; /* Which instrument are we referring to? */ - tail = *vxi11_clients; + tail = *clients; while (tail) { if (strncmp(address, tail->address, 20) == 0) { client = tail; @@ -224,7 +246,7 @@ int vxi11_close_device(VXI11_CLINK * clink, const char *address, struct _vxi11_c if (last) { last->next = client->next; } else { - *vxi11_clients = client->next; + *clients = client->next; } } } diff --git a/library/vxi11_user.h b/library/vxi11_user.h index 87a055b..84fcc79 100644 --- a/library/vxi11_user.h +++ b/library/vxi11_user.h @@ -45,7 +45,7 @@ extern "C" { #define LIBVXI11_MAJOR 2 -#define LIBVXI11_MINOR 0 +#define LIBVXI11_MINOR 1 #define LIBVXI11_REVISION 0 /* LIBVXI11_VERSION_NUMBER looks like 2002001 for e.g. version 2.2.1. */ #define LIBVXI11_VERSION_NUMBER (LIBVXI11_MAJOR*1000000+LIBVXI11_MINOR*1000+LIBVXI11_REVISION) @@ -67,15 +67,14 @@ typedef struct _VXI11_CLINK VXI11_CLINK; #define VXI11_NULL_WRITE_RESP 51 /* client list stucture */ -struct _vxi11_client_t { +typedef struct _vxi11_client_t { struct _vxi11_client_t *next; char address[20]; #ifndef WIN32 CLIENT *client_address; #endif int link_count; -}; -typedef struct _vxi11_client_t vxi11_client_t; +} vxi11_client_t; /* Function: vxi11_library_version * @@ -113,7 +112,28 @@ vx_EXPORT int vxi11_lib_version(int *major, int *minor, int *revision); * 0 - on success * 1 - on failure. clink will not be a valid pointer. */ -vx_EXPORT int vxi11_open_device(VXI11_CLINK **clink, const char *address, char *device, struct _vxi11_client_t **vxi11_clients); +vx_EXPORT int vxi11_open_device(VXI11_CLINK **clink, const char *address, char *device); + + +/* Function: vxi11_open_device_clients + * + * Open a connection to an instrument. + * + * Parameters: + * clink - pointer to a VXI11_CLINK pointer, will be initialised on a + * successful connection. + * address - the IP address or (where supported) USB address for the + * instrument to connect to. + * device - some instruments have multiple interfaces, this allows you to + * specify which to connect to. Set to NULL to use the default of + * "inst0". + * clients - pointer to a vxi11_clients structure + * + * Returns: + * 0 - on success + * 1 - on failure. clink will not be a valid pointer. + */ +vx_EXPORT int vxi11_open_device_clients(VXI11_CLINK **clink, const char *address, char *device, vxi11_client_t **clients); /* Function: vxi11_close_device @@ -126,7 +146,21 @@ vx_EXPORT int vxi11_open_device(VXI11_CLINK **clink, const char *address, char * * Returns: * 0 - on success */ -vx_EXPORT int vxi11_close_device(VXI11_CLINK *clink, const char *address, struct _vxi11_client_t **vxi11_clients); +vx_EXPORT int vxi11_close_device(VXI11_CLINK *clink, const char *address); + + +/* Function: vxi11_close_device_clients + * + * Parameters: + * clink - a valid VXI11_CLINK pointer. + * address - the IP address or (where supported) USB address for the + * instrument. + * clients - pointer to a vxi11_clients structure + * + * Returns: + * 0 - on success + */ +vx_EXPORT int vxi11_close_device_clients(VXI11_CLINK *clink, const char *address, vxi11_client_t **clients); /* Function: vxi11_send From 809258469f1e4c6610da5fc5a842198a3a2ae753 Mon Sep 17 00:00:00 2001 From: Tom Levens Date: Wed, 16 Jan 2019 06:01:27 +0100 Subject: [PATCH 4/5] Bump minor version --- Makefile | 2 +- library/linker.version | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 7761e9e..e28bf8c 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -VERSION=2.0 +VERSION=2.1 include config.mk diff --git a/library/linker.version b/library/linker.version index b82bbf3..4b9a8e4 100644 --- a/library/linker.version +++ b/library/linker.version @@ -2,7 +2,7 @@ * symbols are exported. */ -VXI11_2.0 { +VXI11_2.1 { global: vxi11_close_device; vxi11_close_device_clients; From 5d96ccfad4f6f58d7f3ec31c3eb3a0ee356036b8 Mon Sep 17 00:00:00 2001 From: Tom Levens Date: Wed, 16 Jan 2019 06:02:00 +0100 Subject: [PATCH 5/5] Modify Makefiles to allow static library build --- .gitignore | 7 +++++-- library/Makefile | 32 +++++++++++++++++++++++--------- utils/Makefile | 11 +++-------- 3 files changed, 31 insertions(+), 19 deletions(-) diff --git a/.gitignore b/.gitignore index 53d5e2c..54ee763 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ build/ +build-static/ +build-shared/ vxi11.h vxi11_cmd vxi11_clnt.c @@ -8,9 +10,10 @@ TAGS vxi11_test.cc vxi11_test.cc docs -libvxi11.so.0 +libvxi11.a +libvxi11.so +libvxi11.so.* vxi11_send *.o *.pyc .pc/ -libvxi11.a diff --git a/library/Makefile b/library/Makefile index 881b419..f9d7bd2 100644 --- a/library/Makefile +++ b/library/Makefile @@ -1,6 +1,6 @@ include ../config.mk -.PHONY : all install clean dist distclean +.PHONY : all static shared install clean dist distclean UNAME:=$(shell uname -s) @@ -8,31 +8,45 @@ ifneq ($(UNAME),SunOS) LDFLAGS:=$(LDFLAGS) -Wl,--version-script=linker.version endif -all : libvxi11.so.${SOVERSION} +OBJ:=vxi11_user.o vxi11_clnt.o vxi11_xdr.o +SDIR:=build-static +DDIR:=build-shared -libvxi11.so.${SOVERSION} : vxi11_user.o vxi11_clnt.o vxi11_xdr.o +all : static shared +static : libvxi11.a +shared : libvxi11.so + +libvxi11.so : libvxi11.so.${SOVERSION} + ln -sf libvxi11.so.${SOVERSION} libvxi11.so + +libvxi11.so.${SOVERSION} : $(addprefix ${DDIR}/,${OBJ}) $(CC) $(LDFLAGS) -shared -Wl,-soname,libvxi11.so.${SOVERSION} $^ -o $@ -vxi11_user.o: vxi11_user.c vxi11.h - $(CC) -fPIC $(CFLAGS) -c $< -o $@ +libvxi11.a : $(addprefix ${SDIR}/,${OBJ}) + $(AR) rcs $@ $^ -vxi11_clnt.o : vxi11_clnt.c +${DDIR}/%.o : %.c vxi11.h | ${DDIR} $(CC) -fPIC $(CFLAGS) -c $< -o $@ -vxi11_xdr.o : vxi11_xdr.c - $(CC) -fPIC $(CFLAGS) -c $< -o $@ +${SDIR}/%.o : %.c vxi11.h | ${SDIR} + $(CC) $(CFLAGS) -c $< -o $@ vxi11.h vxi11_clnt.c vxi11_xdr.c : vxi11.x rpcgen -M vxi11.x +${SDIR} ${DDIR}: + @mkdir $@ + TAGS: $(wildcard *.c) $(wildcard *.h) $(wildcard *.c) etags $^ clean: - rm -f *.o libvxi11.so.${SOVERSION} vxi11.h vxi11_svc.c vxi11_xdr.c vxi11_clnt.c TAGS + rm -rf ${SDIR} ${DDIR} + rm -f *.o libvxi11.so libvxi11.so.${SOVERSION} libvxi11.a vxi11.h vxi11_svc.c vxi11_xdr.c vxi11_clnt.c TAGS install: all $(INSTALL) -d $(DESTDIR)$(prefix)/lib${LIB_SUFFIX}/ + $(INSTALL) libvxi11.a $(DESTDIR)$(prefix)/lib${LIB_SUFFIX}/ $(INSTALL) libvxi11.so.${SOVERSION} $(DESTDIR)$(prefix)/lib${LIB_SUFFIX}/ ln -sf libvxi11.so.${SOVERSION} $(DESTDIR)$(prefix)/lib${LIB_SUFFIX}/libvxi11.so $(INSTALL) -d $(DESTDIR)$(prefix)/include/ diff --git a/utils/Makefile b/utils/Makefile index d73a8f7..c30f067 100644 --- a/utils/Makefile +++ b/utils/Makefile @@ -3,19 +3,14 @@ include ../config.mk .PHONY : all install clean CFLAGS:=${CFLAGS} -I../library +LDFLAGS:=${LDFLAGS} -L../library -lvxi11 all : vxi11_cmd vxi11_send -vxi11_cmd: vxi11_cmd.o ../library/libvxi11.so.${SOVERSION} +vxi11_cmd vxi11_send: %: %.o $(CC) -o $@ $^ $(LDFLAGS) -vxi11_cmd.o: vxi11_cmd.c ../library/vxi11_user.c ../library/vxi11.h - $(CC) $(CFLAGS) -c $< -o $@ - -vxi11_send: vxi11_send.o ../library/libvxi11.so.${SOVERSION} - $(CC) -o $@ $^ $(LDFLAGS) - -vxi11_send.o: vxi11_send.c ../library/vxi11_user.c ../library/vxi11.h +%.o: %.c $(CC) $(CFLAGS) -c $< -o $@ clean: