This commit is contained in:
Alex Lin 2019-03-26 17:10:16 -05:00
commit 6a84ae548b
15 changed files with 211 additions and 99 deletions

View File

@ -15,10 +15,19 @@ $trick_home = dirname($trick_bin) ;
#### Handle arguments ####
$numArgs = $#ARGV + 1;
$makefileAddArgs = ' ';
$sdefine_dir = ".";
$sdefine = "S_define";
$makefile = "makefile";
foreach $argnum (0 .. $#ARGV) {
$arg = $ARGV[$argnum];
if ($arg =~ /(\w+)=(\w+)/ ) {
$makefileAddArgs = $makefileAddArgs . $1 . "=" . $2 . " ";
} elsif ($arg eq "-C" || $arg eq "--directory" ) {
$sdefine_dir = abs_path($ARGV[$argnum + 1]);
$makefileAddArgs = $makefileAddArgs . " -C $sdefine_dir ";
$sdefine = $sdefine_dir . "/${sdefine}";
$makefile = $sdefine_dir . "/${makefile}";
shift
} elsif ($arg =~ /-d/ ) {
$makefileAddArgs = $makefileAddArgs . " debug ";
} elsif ($arg =~ /-t/ ) {
@ -30,17 +39,17 @@ foreach $argnum (0 .. $#ARGV) {
}
}
if ( -f "S_define" ) {
if ( not -w "." ) {
print getcwd() , " is not writable\n" ;
print "CP aborted\n" ;
if ( -f $sdefine ) {
if ( not -w $sdefine_dir ) {
print $sdefine_dir , " is not writable\n" ;
print "trick-CP aborted\n" ;
exit 1 ;
}
unlink "build/Makefile_sim", "makefile" ;
unlink "build/Makefile_sim", $makefile ;
$makefile_text = do { local $/; <main::DATA> } ;
$makefile_text =~ s/SUB_TRICK_HOME/$trick_home/ ;
$makefile_text =~ s/SUB_TRICK_BIN/$trick_bin/ ;
open MAKEFILE, ">makefile" ;
open MAKEFILE, ">$makefile" ;
print MAKEFILE $makefile_text ;
close MAKEFILE ;
system("make -f makefile " . $makefileAddArgs) ;
@ -90,6 +99,11 @@ Print the trick-CP help message (this message)
Send CP output to FILE_NAME
=item B<-C> | B<--directory> I<SIM_DIRECTORY_NAME>
Build a simulation located in a different directory than the current
working directory.
=item B<-p> | B<--no-python>
Exclude python input processor from simulation.

View File

@ -121,6 +121,9 @@ namespace Trick {
/** Current file size for data record file in bytes.\n */
uint64_t total_bytes_written; /**< trick_io(**) trick_units(--) */
/** Bool to signify that the warning for reaching max filesize has been printed */
bool max_size_warning;
/** Buffer to hold formatted data ready for disk or other destination.\n */
char * writer_buff ; /**< trick_io(**) trick_units(--) */

View File

@ -10,6 +10,7 @@
#include <queue>
#include <vector>
#include <string>
#include <iostream>
#include <pthread.h>
#include "trick/tc.h"
#include "trick/reference.h"
@ -39,6 +40,11 @@ namespace Trick {
*/
~VariableServer() ;
/**
@brief Write a JSON encoded list of Variable Server Connections to the given stream.
*/
friend std::ostream& operator<< (std::ostream& s, Trick::VariableServer& vs);
/**
@brief Set up the listen port during default_data so it is available at the start of initialization.
*/

View File

@ -6,6 +6,7 @@
#ifndef VARIABLESERVERREFERENCE_HH
#define VARIABLESERVERREFERENCE_HH
#include <iostream>
#include "trick/reference.h"
union cv_converter ;
@ -24,6 +25,8 @@ namespace Trick {
VariableReference(REF2 * in_ref) ;
~VariableReference() ;
friend std::ostream& operator<< (std::ostream& s, const Trick::VariableReference& vref);
/** Pointer to trick variable reference structure.\n */
REF2 * ref ;
cv_converter * conversion_factor ; // ** udunits conversion factor

View File

@ -8,6 +8,7 @@
#include <vector>
#include <string>
#include <iostream>
#include <pthread.h>
#include "trick/tc.h"
#include "trick/ThreadBase.hh"
@ -27,6 +28,8 @@ namespace Trick {
public:
enum ConnectionType { TCP, UDP, MCAST } ;
friend std::ostream& operator<< (std::ostream& s, Trick::VariableServerThread& vst);
/**
@brief Constructor.
@param listen_dev - the TCDevice set up in listen()

View File

@ -6,6 +6,7 @@
extern "C" {
#endif
void var_server_list_connections(void);
const char * var_server_get_hostname(void) ;
unsigned short var_server_get_port(void) ;

View File

@ -1,6 +1,6 @@
# This file can be used to create an object file containing the io_* and py_*
# code that Trick would normally generate during the simulation build process.
# Sims can then link against this object file, reducing compilation time.
# This file can be used to create an object file or library containing the io_*
# and py_* code that Trick would normally generate during the simulation build
# process. Sims can then link against that, reducing compilation time.
#
# To use it, create a directory that includes a file named S_source.hh that
# includes all header files for which you want io_* and py_* code generated.
@ -25,9 +25,26 @@
# paths to the header files included by your S_source.hh. For instance:
# -I$(HOME)/myproject/foo/include -I$(HOME)/myproject/bar/include
#
# TRICKIFY_BUILD_TYPE (optional)
# Valid options are:
# 1. STATIC (.a)
# Create a static library. This will require the use of --whole-archive (on
# Linux) or -all_load/-force_load (on Mac) when linking the sim executeable.
# Trick uses dlsym to dynamically load symbols at run time, but the linker,
# by default, will not include symbols from static libraries that are not
# known to be needed at compile time.
# 2. SHARED (.so)
# Create a shared object (dynamically linked library). This may require the
# use of -rpath to ensure the linker can find the shared object at runtime
# unless you explicitly link against it (as opposed to using -L and -l)
# during compilation.
# 3. PLO (.o) [default]
# Create a partially-linked object. No special linker options are required.
#
# TRICKIFY_OBJECT_NAME (optional)
# The name of the generated object file. The default value is trickified.o.
# You should choose something more meaningful, like trickified_myproject.o.
# The name of the generated object file or library. The default value is
# trickified.o. You should choose something more meaningful, especially if
# you're using another build type.
#
# TRICKIFY_PTYON_DIR (optional)
# The directory into which generated Python modules are placed. The default
@ -74,9 +91,11 @@ ifndef TRICKIFY_CXX_FLAGS
$(error TRICKIFY_CXX_FLAGS must be set)
endif
TRICKIFY_BUILD_TYPE ?= PLO
TRICKIFY_OBJECT_NAME ?= trickified.o
TRICKIFY_PYTHON_DIR ?= python
TRICK_HOME := $(abspath $(dir $(lastword $(MAKEFILE_LIST)))/../../..)
MAKE_OUT ?= build/MAKE_out
ifneq ($(wildcard build),)
SWIG_OBJECTS := $(shell cat build/S_library_swig)
@ -92,30 +111,26 @@ TRICK_CXXFLAGS += $(TRICKIFY_CXX_FLAGS)
# Ensure we can process all headers
TRICK_EXT_LIB_DIRS :=
# When given a library, the linker will only link in objects that are known to
# be needed at link time. However, Trick uses dlsym to dynamically load the
# objects we'll be creating here. It cannot be known which objects will be
# needed at link time, so the sim has to link them all. In that case, we might
# as well create an object (which will be fully linked in by the sim) instead
# of a library (which would require the use of the -whole-archive option).
#
# One disadvantage of this approach is that we have to link all of the objects
# in this rule no matter how many have changed, whereas ar would allow us to
# replace only the changed objects. However, Trickified projects are
# necessarily used as third-party libraries, and so would be expected to
# change infrequently. Moreover, the methods for force-linking a library differ
# between Linux and Mac, so obviating the need for it simplifies a Trickified
# project's user-facing makefile.
$(TRICKIFY_OBJECT_NAME): $(SWIG_OBJECTS) $(IO_OBJECTS) | $(dir $(TRICKIFY_OBJECT_NAME))
$(info $(call COLOR,Linking) $@)
@ld -r -o $@ $^
ifeq ($(TRICKIFY_BUILD_TYPE),PLO)
@echo $(LD) $(LD_PARTIAL) -o $@ $^ >> $(MAKE_OUT)
$(ECHO_CMD)ld -r -o $@ $^ 2>&1 | $(TEE) -a $(MAKE_OUT); exit $${PIPESTATUS[0]}
else ifeq ($(TRICKIFY_BUILD_TYPE),SHARED)
@echo $(TRICK_CPPC) -shared -o $@ $^ >> $(MAKE_OUT)
$(ECHO_CMD)c++ -shared -o $@ $^ 2>&1 | $(TEE) -a $(MAKE_OUT); exit $${PIPESTATUS[0]}
else ifeq ($(TRICKIFY_BUILD_TYPE),STATIC)
@echo ar rcs $@ $^ >> $(MAKE_OUT)
$(ECHO_CMD)ar rcs $@ $^ 2>&1 | $(TEE) -a $(MAKE_OUT); exit $${PIPESTATUS[0]}
endif
$(dir $(TRICKIFY_OBJECT_NAME)) $(TRICKIFY_PYTHON_DIR) build:
@mkdir -p $@
$(IO_OBJECTS): %.o: %.cpp
$(info $(call COLOR,Compiling) $<)
@$(TRICK_CPPC) $(TRICK_CXXFLAGS) $(TRICK_SYSTEM_CXXFLAGS) -std=c++11 -Wno-invalid-offsetof -MMD -MP -c -o $@ $<
@echo $(TRICK_CPPC) $(TRICK_CXXFLAGS) $(TRICK_SYSTEM_CXXFLAGS) -std=c++11 -Wno-invalid-offsetof -MMD -MP -c -o $@ $< >> $(MAKE_OUT)
$(ECHO_CMD)$(TRICK_CPPC) $(TRICK_CXXFLAGS) $(TRICK_SYSTEM_CXXFLAGS) -std=c++11 -Wno-invalid-offsetof -MMD -MP -c -o $@ $< 2>&1 | $(TEE) -a $(MAKE_OUT) ; exit $${PIPESTATUS[0]}
$(IO_OBJECTS:.o=.d): %.d: ;
@ -123,16 +138,19 @@ $(IO_OBJECTS:.o=.d): %.d: ;
$(SWIG_OBJECTS): %.o: %.cpp
$(info $(call COLOR,Compiling) $<)
@$(TRICK_CPPC) $(TRICK_CXXFLAGS) $(TRICK_SYSTEM_CXXFLAGS) $(PYTHON_INCLUDES) -Wno-unused-parameter -Wno-shadow -c -o $@ $<
@echo $(TRICK_CPPC) $(TRICK_CXXFLAGS) $(TRICK_SYSTEM_CXXFLAGS) $(PYTHON_INCLUDES) -Wno-unused-parameter -Wno-shadow -c -o $@ $< >> $(MAKE_OUT)
$(ECHO_CMD)$(TRICK_CPPC) $(TRICK_CXXFLAGS) $(TRICK_SYSTEM_CXXFLAGS) $(PYTHON_INCLUDES) -Wno-unused-parameter -Wno-shadow -c -o $@ $< 2>&1 | $(TEE) -a $(MAKE_OUT) ; exit $${PIPESTATUS[0]}
$(SWIG_OBJECTS:.o=.cpp): %.cpp: %.i | $(TRICKIFY_PYTHON_DIR) $(SWIG_OBJECTS:.o=.i)
$(info $(call COLOR,SWIGing) $<)
@$(SWIG) $(TRICK_INCLUDE) $(TRICK_DEFINES) $(TRICK_VERSIONS) $(TRICK_SWIG_FLAGS) -c++ -python -includeall -ignoremissing -w201,303,325,362,389,401,451 -outdir $(TRICKIFY_PYTHON_DIR) -o $@ $<
@echo $(SWIG) $(TRICK_INCLUDE) $(TRICK_DEFINES) $(TRICK_VERSIONS) $(TRICK_SWIG_FLAGS) -c++ -python -includeall -ignoremissing -w201,303,325,362,389,401,451 -outdir $(TRICKIFY_PYTHON_DIR) -o $@ $< >> $(MAKE_OUT)
$(ECHO_CMD)$(SWIG) $(TRICK_INCLUDE) $(TRICK_DEFINES) $(TRICK_VERSIONS) $(TRICK_SWIG_FLAGS) -c++ -python -includeall -ignoremissing -w201,303,325,362,389,401,451 -outdir $(TRICKIFY_PYTHON_DIR) -o $@ $< 2>&1 | $(TEE) -a $(MAKE_OUT) ; exit $${PIPESTATUS[0]}
define create_convert_swig_rule
build/%_py.i: /%.$1
$$(info $$(call COLOR,Converting) $$<)
${TRICK_HOME}/$(LIBEXEC)/trick/convert_swig ${TRICK_CONVERT_SWIG_FLAGS} $$<
@echo ${TRICK_HOME}/$(LIBEXEC)/trick/convert_swig ${TRICK_CONVERT_SWIG_FLAGS} $$< >> $(MAKE_OUT)
$(ECHO_CMD)${TRICK_HOME}/$(LIBEXEC)/trick/convert_swig ${TRICK_CONVERT_SWIG_FLAGS} $$< 2>&1 | $(TEE) -a $(MAKE_OUT) ; exit $$${PIPESTATUS[0]}
endef
EXTENSIONS := H h hh hxx h++ hpp
@ -170,8 +188,9 @@ $(foreach EXTENSION,$(EXTENSIONS),$(eval $(call create_convert_swig_rule,$(EXTEN
# http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/
build/S_source.d: | $(dir $@)
@$(TRICK_HOME)/bin/trick-ICG $(TRICK_CXXFLAGS) $(TRICK_SYSTEM_CXXFLAGS) $(TRICK_ICGFLAGS) S_source.hh
@$(TRICK_HOME)/$(LIBEXEC)/trick/make_makefile_swig
@$(TRICK_CC) -MM -MP -MT $@ -MF $@ $(TRICKIFY_CXX_FLAGS) S_source.hh
$(ECHO_CMD)$(TRICK_HOME)/bin/trick-ICG $(TRICK_CXXFLAGS) $(TRICK_SYSTEM_CXXFLAGS) $(TRICK_ICGFLAGS) S_source.hh
$(ECHO_CMD)$(TRICK_HOME)/$(LIBEXEC)/trick/make_makefile_swig 2>&1 | $(TEE) -a $(MAKE_OUT) ; exit $${PIPESTATUS[0]}
@echo $(TRICK_CC) -MM -MP -MT $@ -MF $@ $(TRICKIFY_CXX_FLAGS) S_source.hh >> $(MAKE_OUT)
$(ECHO_CMD) $(TRICK_CC) -MM -MP -MT $@ -MF $@ $(TRICKIFY_CXX_FLAGS) S_source.hh 2>&1 | $(TEE) -a $(MAKE_OUT) ; exit $${PIPESTATUS[0]}
-include build/S_source.d

View File

@ -112,27 +112,6 @@ static void _mkdir(const char *dir) {
}
}
// this is a subset of tests on the header file to determine if this file is not excluded for any reason.
bool PrintAttributes::isFileIncluded(std::string header_file_name) {
// several tests require the real path of the header file.
char * realPath = almostRealPath(header_file_name.c_str()) ;
if ( realPath != NULL ) {
// Only include user directories (not system dirs like /usr/include)
if ( hsd.isPathInUserDir(realPath) ) {
// Don't process files in excluded directories
if ( (hsd.isPathInExclude(realPath) == false) and (hsd.isPathInICGExclude(realPath) == false) ) {
// Only include files that do not have ICG: (No)
// hasICGNo uses original header name, not the real path
if ( ! cs.hasICGNo(header_file_name) ) {
return true ;
}
}
}
}
return false ;
}
bool PrintAttributes::openIOFile(const std::string& header_file_name) {
/**
* There are a lot of conditions to be met in order to open an IO file. We store the headers
@ -258,18 +237,9 @@ void PrintAttributes::printClass( ClassValues * cv ) {
outfile.close();
}
if (!isHeaderExcluded(fileName)) {
if (!isHeaderExcluded(fileName, false)) {
printer->printClassMap(class_map_outfile, cv);
}
/*
char* realPath = almostRealPath(fileName.c_str());
if (realPath) {
if (isFileIncluded(fileName) or hsd.isPathInExtLib(realPath)) {
printer->printClassMap(class_map_outfile, cv);
}
free(realPath);
}
*/
}
void PrintAttributes::printEnum(EnumValues* ev) {
@ -293,14 +263,9 @@ void PrintAttributes::printEnum(EnumValues* ev) {
outfile.close() ;
}
if (!isHeaderExcluded(fileName)) {
if (!isHeaderExcluded(fileName), false) {
printer->printEnumMap(enum_map_outfile, ev);
}
/*
if (isFileIncluded(fileName)) {
printer->printEnumMap(enum_map_outfile, ev) ;
}
*/
}
void PrintAttributes::createMapFiles() {

View File

@ -101,7 +101,6 @@ class PrintAttributes {
bool openIOFile(const std::string& header_file_name) ;
bool isFileIncluded(std::string header_file_name) ;
bool isIOFileOutOfDate(std::string header_file_name, std::string io_file_name ) ;
bool hasBeenProcessed(EnumValues& enumValues);
bool hasBeenProcessed(ClassValues& classValues);

View File

@ -40,48 +40,58 @@ bool TranslationUnitVisitor::TraverseDecl(clang::Decl *d) {
break ;
case clang::Decl::CXXRecord : {
clang::CXXRecordDecl * crd = static_cast<clang::CXXRecordDecl *>(d) ;
clang::RecordDecl * rd = crd->getDefinition() ;
bool is_forward_declaration = false;
/* The definition of the record must exist before we can process it. The definition is
NULL when this is only a forward declaration of a class */
if ( rd == NULL ) {
is_forward_declaration = true;
}
/* Sometimes rd is not NULL when we still only have a forward declaration because
the file that defines the class is included before processing this fwd declare.
In this case the CXXRecordDecl file name will not match the current file name, and is
in fact empty */
clang::RecordDecl * rd = crd->getDefinition() ;
if ( rd != NULL ) {
else {
std::string rd_file = getFileName(ci , rd->RBRACELOC(), hsd) ;
std::string crd_file = getFileName(ci , crd->RBRACELOC(), hsd) ;
if (!crd_file.empty() and !crd_file.compare(rd_file)) {
//crd->dump() ; std::cout << std::endl ;
if ( isInUserCode(ci , crd->RBRACELOC(), hsd) ) {
CXXRecordVisitor cvis(ci , cs, hsd , pa, true) ;
cvis.TraverseCXXRecordDecl(static_cast<clang::CXXRecordDecl *>(d)) ;
pa.printClass(cvis.get_class_data()) ;
/* Check to see if the struct/class is forward declared in the same file.
If it is, then remove the notation that it is forward declared. This
is to allow C structs to be forward declared and typedeffed and io_src
code will be generated for both the original structure name and typedeffed
name.
struct Astruct ;
typedef struct Astruct {} Bstruct ;
*/
std::set< std::string >::iterator it ;
std::string file_name = getFileName(ci , d->GETLOCEND(), hsd) ;
std::string source_type = cvis.get_class_data()->getName() ;
it = fwd_declared_classes[file_name].find(source_type) ;
if ( it != fwd_declared_classes[file_name].end() ) {
fwd_declared_classes[file_name].erase(it) ;
}
}
if (crd_file.empty() || crd_file.compare(rd_file)) {
is_forward_declaration = true;
}
} else {
}
if (is_forward_declaration) {
// These are forward declarations. Insert this into the set of fwd declares keyed by the current file.
if ( ! crd->getNameAsString().empty() ) {
fwd_declared_classes[getFileName(ci , d->GETLOCEND(), hsd)].insert(crd->getNameAsString()) ;
}
}
else {
//crd->dump() ; std::cout << std::endl ;
if ( isInUserCode(ci , crd->RBRACELOC(), hsd) ) {
CXXRecordVisitor cvis(ci , cs, hsd , pa, true) ;
cvis.TraverseCXXRecordDecl(static_cast<clang::CXXRecordDecl *>(d)) ;
pa.printClass(cvis.get_class_data()) ;
/* Check to see if the struct/class is forward declared in the same file.
If it is, then remove the notation that it is forward declared. This
is to allow C structs to be forward declared and typedeffed and io_src
code will be generated for both the original structure name and typedeffed
name.
struct Astruct ;
typedef struct Astruct {} Bstruct ;
*/
std::set< std::string >::iterator it ;
std::string file_name = getFileName(ci , d->GETLOCEND(), hsd) ;
std::string source_type = cvis.get_class_data()->getName() ;
it = fwd_declared_classes[file_name].find(source_type) ;
if ( it != fwd_declared_classes[file_name].end() ) {
fwd_declared_classes[file_name].erase(it) ;
}
}
}
}
break ;
case clang::Decl::Enum : {

View File

@ -73,6 +73,7 @@ Trick::DataRecordGroup::DataRecordGroup( std::string in_name ) :
writer_num(0),
max_file_size(1<<30), // 1 GB
total_bytes_written(0),
max_size_warning(false),
writer_buff(NULL),
single_prec_only(false),
buffer_type(DR_Buffer),
@ -692,6 +693,14 @@ int Trick::DataRecordGroup::write_data(bool must_write) {
writer_num++ ;
}
if(!max_size_warning && (total_bytes_written > max_file_size)) {
std::cerr << "WARNING: Data record max file size " << (static_cast<double>(max_file_size))/(1<<20) << "MB reached.\n"
"https://github.com/nasa/trick/wiki/Data-Record#changing-the-max-file-size-of-a-data-record-group-ascii-and-binary-only"
<< std::endl;
max_size_warning = true;
}
pthread_mutex_unlock(&buffer_mutex) ;
}

View File

@ -63,6 +63,16 @@ Trick::VariableReference::VariableReference(REF2 * in_ref ) {
}
std::ostream& Trick::operator<< (std::ostream& s, const Trick::VariableReference& vref) {
if (vref.ref->reference != NULL) {
s << " \"" << vref.ref->reference << "\"";
} else {
s<< " null";
}
return s;
}
Trick::VariableReference::~VariableReference() {
free(ref) ;
free(buffer_in) ;

View File

@ -1,5 +1,6 @@
#include <netdb.h>
#include <iostream>
#include "trick/VariableServer.hh"
#include "trick/tc_proto.h"
@ -17,6 +18,26 @@ Trick::VariableServer::VariableServer() :
Trick::VariableServer::~VariableServer() {
}
std::ostream& Trick::operator<< (std::ostream& s, Trick::VariableServer& vs) {
std::map < pthread_t , VariableServerThread * >::iterator it ;
s << "{\"variable_server_connections\":[" << std::endl;
int count = 0;
int n_connections = (int)vs.var_server_threads.size();
for ( it = vs.var_server_threads.begin() ; it != vs.var_server_threads.end() ; it++ ) {
s << "{" << std::endl;
s << *(*it).second;
s << "}";
if ((n_connections-count)>1) {
s << "," ;
}
s << std::endl;
count ++;
}
s << "]}" << std::endl;
return s;
}
bool Trick::VariableServer::get_enabled() {
return enabled ;
}

View File

@ -1,4 +1,5 @@
#include <iostream>
#include <stdlib.h>
#include "trick/VariableServerThread.hh"
#include "trick/exec_proto.h"
@ -63,6 +64,50 @@ Trick::VariableServerThread::~VariableServerThread() {
free( stripped_msg ) ;
}
std::ostream& Trick::operator<< (std::ostream& s, Trick::VariableServerThread& vst) {
std::vector <Trick::VariableReference *>::iterator it;
struct sockaddr_in otherside;
socklen_t len = (socklen_t)sizeof(otherside);
s << " \"connection\":{" << std::endl;
s << " \"client_tag\":\"" << vst.connection.client_tag << "\"," << std::endl;
int err = getpeername(vst.connection.socket, (struct sockaddr*)&otherside, &len);
if (err == 0) {
s << " \"client_IP_address\":\"" << inet_ntoa(otherside.sin_addr) << "\"," << std::endl;
s << " \"client_port\":\"" << ntohs(otherside.sin_port) << "\"," << std::endl;
} else {
s << " \"client_IP_address\":\"unknown\"," << std::endl;
s << " \"client_port\":\"unknown\"," << std::endl;
}
if (vst.binary_data) {
s << " \"format\":\"BINARY\",";
} else {
s << " \"format\":\"ASCII\",";
}
s << std::endl;
s << " \"update_rate\":" << vst.update_rate << "," << std::endl;
s << " \"variables\":[" << std::endl;
int n_vars = (int)vst.vars.size();
for (int i=0 ; i<n_vars ; i++) {
s << *(vst.vars[i]);
if ((n_vars-i)>1) {
s << "," ;
}
s << std::endl;
}
s << " ]" << std::endl;
s << " }" << std::endl;
return s;
}
void Trick::VariableServerThread::set_vs_ptr(Trick::VariableServer * in_vs) {
vs = in_vs ;
}

View File

@ -387,6 +387,10 @@ Trick::VariableServer * var_server_get_var_server() {
return the_vs ;
}
extern "C" void var_server_list_connections(void) {
std::cout << *the_vs << std::endl;
}
/**
* @relates Trick::VariableServer
* @copydoc Trick::VariableServer::get_hostname