This chapter provides information about compiling, linking, and debugging your application.
ObjectStore can now be used to store STL objects persistently. There are a number of STL class library implementations available that can be used with ObjectStore. For example, ObjectSpace, Rogue Wave, and Visual C++ offer such implementations.
Microsoft Visual C++ Restriction
ObjectStore Release 5.1 supports ObjectSpace STL, but does not yet support Visual C++ version 5.0 STL. Moving an Application and Its Schema
The ossetasp utility patches an executable so that it looks for its application schema in a database that you specify.
Syntax
ossetasp -p executable ossetasp executable database
When you move or copy an ObjectStore application to a machine that is not running a Server, leave the application schema database on the Server host. Normally, the application schema database must be local to the Server.
After you copy or move an application to another machine, you must patch the executable so that it can find the application schema database. Run the ossetasp utility with the absolute pathname of the application schema database. Be sure to specify the name of the Server host.
A locator file allows a database and its application schema to be on a machine other than the Server host. See ObjectStore Management, Chapter 5, Using Locator Files to Set Up Server-Remote Databases.
Windows NT
On Windows NT systems, you can run the ossetasp utility on any executable or DLL that contains schema (that is, that has a schema object file produced by ossg linked into it). Restrictions
This utility is available on all platforms except OS/2. On OS/2, as well as on all other platforms, you can use objectstore::get_application_schema_pathname(). See theObjectStore C++ API Reference, Chapter 2, Class Library, for details.
Working with Virtual Function Table (VTBL) Pointers and Discriminant Functions
There are two special cases in which ObjectStore needs to know, at run time, the locations of information in your application program's executable:
Relocation
When ObjectStore reads in an object with virtual functions, it supplies an appropriate vtbl pointer from the current application. This is called vtbl relocation. Missing VTBLs
Depending on your platform, missing vtbls can cause errors at compile time or at run time. It is better to find such errors at compile time. By default ossg reports these errors at compile time. An optional ossg flag, -weak_symbols, can be used to suppress the default behavior. See Chapter 3, Generating Schemas, for detailed information about ossg syntax.
Symbols Missing When Linking ObjectStore Applications
Sometimes when linking, particularly with optimizations enabled, you are told that various symbols required by the application schema object file are missing. These symbols on non-Windows platforms (including OS/2) begin with __vtbl or __vft, or end with __vtbl. On Windows the symbols begin with ??_7. This happens because ObjectStore needs access to the virtual function tables (vfts) for some classes, and the C++ compiler does not recognize these tables as being needed. The easiest way to get these symbols is to add a nonstatic dummy function such as the following
void foo_force_vfts(void*){ force_vfts(new A); foo_force_vfts(new B);Creating instances of a class causes the class's vfts, as well as those of bases that have out-of-line default constructors, to be created in this file.
... }
class A { virtual void foo() = 0; }; class B : public A { virtual void foo(); };then class A might be missing its vft. However, an unoptimized new B would call A's inline default constructor, which would reference the vft for A. But if class B had an out-of-line constructor, this would not work. Then it would be easiest to make an out-of-line constructor for A:
class A { virtual void foo() = 0; A(){} friend void force_vfts(void*); A(void*); }; class B : public A { virtual void foo(); };and define A::A(void*){} in some file.
void foo_force_vfts(void*) { foo_force_vfts(new os_Set< missing-type>); foo_force_vfts(new os_List< missing-type>); foo_force_vfts(new os_Array< missing-type>); foo_force_vfts(new os_Bag< missing-type>); foo_force_vfts(new os_Collection< missing-type>); }There are additional considerations for building applications that use collections. See Instantiation Problem with Template Collection Classes.
Run-Time Errors from Missing VTBLs
On some platforms (without weak symbol support), you find out about the missing vtbls at link time. The vtbls are marked in the schema output file, but are not marked in the application. This is frequently the case for parameterized collections classes (os_Set, os_List, and so on). No constructor
Missing vtbls can occur when your application calls a virtual function on an instance of a class for which no constructor call appears in the source. Since a call to the class's constructor does not appear in the source, the linker does not recognize the class as being used and does not link in its implementation. But an ObjectStore application can use a class whose constructor it never calls by reading an instance of the class from a database. To avoid this situation, put a call to the class's constructor inside a dummy function that is never called. Class not in schema
Missing vtbls can also occur when the class is not included in the application's schema, either because its definition was not included in the source or because the class was only reachable from explicitly marked classes by means of void* pointers. In this case, the solution is to include a definition of the class, or explicitly mark it with OS_MARK_SCHEMA_TYPE(). Inline virtual functions when using noncfront compilers
Noncfront compilers include C Set ++, DEC C++, SGI C++, Sun C++, VisualAge C++, and Visual C++.
To obtain a list of missing vtbls at run time, set the OS_TRACE_MISSING_VTBLS environment parameter. See ObjectStore Management, OS_TRACE_MISSING_VTBLS.
AIX C Set ++ - Virtual Function Table Pointers
When the ObjectStore client reads a page from the Server into your application, it must store correct virtual function table pointers to those objects that have virtual function tables (vfts). To do this, the client must have the addresses of the vfts for the classes in your schema.
class A { public: virtual foo(): int a; A() {a=0;} }; class B : public virtual A { public: virtual foo(); int b; B() {b=1;} }; class C : public B { int c; C() {c=2;} }; int B::foo() {} xlC_r -qinfo=vft -c x.C
"x.C", line 29.1: 1540-017: (W) Return value of type "int" is expected. "x.C", line 1.1: 1540-281: (I) The virtual function table for "A" will be defined where "A::foo() "x.C", line 10.1: 1540-280: (I) The virtual function table for "B" is defined with "extern" links. "x.C", line 20.1: 1540-280: (I) The virtual function table for "C" is defined with "extern" links.The two C Set ++ arguments are -qvftable and -qnovftable. -qvftable instructs C Set ++ to allocate global vfts for all classes visible in the compilation unit. -qnovftable forces all vfts to be referenced externally.
The simplest way to make C Set ++ work with ObjectStore is to create an additional source file that includes the definitions for classes that have static links. Compile it with -qvftable, and link it. This does not avoid the extra static copies of the table in any modules that allocate objects of this class, but it does allow the application schema source file to link to them.
To avoid extra copies, you have to compile all ordinary sources with -qnovftable, and then add -qvftable to the appropriate sources so that each vft is defined exactly one time.
Note that there is still a limitation that ObjectStore cannot completely address - if a shared library that is not itself linked with the ObjectStore library uses C++ allocation, it will not share the copy of _new_handler provided by ObjectStore.
In previous releases on some platforms, ObjectStore provided the osmakedep command. This is no longer the case. Your compiler vendor should supply you with a configuration management tool.
If you copy an on-line version of an ObjectStore makefile from ObjectStore documentation sources, make sure that you have tabs at the beginning of appropriate lines and not spaces.
You must also link with either the libosthr or libosths libraries. You must link with additional ObjectStore libraries according to the features you use in your code, as shown in the following table. If there is more than one library, you must specify them in the order given. See Examples of Passing Libraries to the Linker.
Threads library
The libosthr or libosths library is for threads. Be sure to use the correct threads library for your platform:
Platform | Threads Library |
AIX | libosthr |
Digital UNIX | libosthr |
HP-UX | libosthr or libosths |
IRIX | libosths |
Solaris 2 | libosthr or libosths |
If you have a real threads package, link with the libosthr library. The libosths library is a stub threads library.
IRIX shared process (sproc) restrictions
Use pthreads but not sprocs in ObjectStore Release 5 and later. ObjectStore 5.0 for IRIX does not support concurrent ObjectStore operations (for example, transactions) in more than one process in a shared process group, where the processes are sharing virtual memory. If you want your program to use ObjectStore 5.0, it is best to restrict all ObjectStore operations to a single process in the shared process group. If you want ObjectStore operations in a number of the processes, the program must minimally ensure that
CC -L$(OS_ROOTDIR)/lib -o my_exec main.o os_schema.o foo.o -losNote that the -L$(OS_ROOTDIR)/lib option begins with an uppercase L as in Library.
When using threads (libosthr), while ObjectStore is running in its fault handler, DCE masks most signals. Therefore, when DCE is linked into an ObjectStore application, ObjectStore's fault handler reenables the following signals:
extern "C" void _ODI_set_reenable_mask(unsigned int new_mask); extern "C" unsigned int _ODI_get_reenable_mask();Consult Object Design Technical Support before using these interfaces.
The mask is a bit vector of the signal values. A value of 1 indicates that the corresponding signal is enabled when ObjectStore's fault handler is entered.
Note that _ODI_get_reenable_mask returns 0 if _ODI_set_reenable_mask has not been called.
Also note that regardless of the reenable_mask value, ObjectStore always reenables the signal being handled (SIGSEGV or SIGBUS).
-loscmp -losmop -losqry -loscol -los {-losthr | losths}When building an application that uses the schema evolution feature, specify libraries like this:
-losse -losqry -loscol -los {-losthr | losths}When building an application that uses database utilities, specify the libraries like this:
-losdbu -los {-losthr | losths}If you need all ObjectStore libraries and you need a stub threads library because you do not have real threads, link with the libraries in this order:
{-losse | -loscmp} -losmop -losqry -loscol -los -losdbu -losu -losthsIf you need all ObjectStore libraries and you have a real threads package, link with the libraries in this order:
{-losse | -loscmp} -losmop -losqry -loscol -los -losdbu -losu -losthr
Usually, DEC C++ uses 64 bits for all pointers in generated code. The eXtended Truncated Address Support Option (xtaso), and other #pragma directives and compiler options, let code with 32-bit pointers coexist within this 64-bit operating system environment. If you use only -xtaso, and have 64-bit pointers in the objects stored in your database, then your database will not be heterogeneous.
Note that within a compilation unit, pragma statements allow the user to switch between 32-bit and 64-bit classes selectively. However, ossg deals with these pragma statements at the granularity of a complete top-level class.
If you are uncertain what versions of software are running on your system, check them with the following commands.
To determine the operating system version, enter
uname -aThe response should be of the form
V3.2 148where 148 corresponds to 3.2.C.
To determine the version of the compiler, enter
cxx -V | tail -1The result should be of the form
DEC C++ V5.1-1for DEC OSF/1 (Alpha) or greater.
This means that when you write ObjectStore applications, you need to use some of the methods described in this section to accommodate 32- and 64-bit pointers. Specifically, the considerations you must address are
The pointer size compiler options are -xtaso, -xtaso_short, -vptr_size, and -vptr_size_short. You can accommodate 32- and 64-bit code using the -xtaso and -vptr_size or -xtaso_short and -vptr_size_short compiler options. The following table describes the compiler options:
Whenever any of these options is specified on the command line, the following actions occur:
To use ObjectStore with the DEC C++ compiler, you must select one of the following methods of protecting pointer size assumptions:
If heterogeneity is not a consideration for your application and you are not concerned with the amount of memory used for 64-bit pointers, you can take advantage of the 64-bit operating system environment and compile using the -xtaso option. This option makes 64 bits the default pointer size and uses 32-bit pointers for particular declarations. In such a case, it is possible to use third-party class libraries that only support 64-bit pointers. See "Using the -xtaso option" for details about using this option.
If heterogeneity is an important consideration for your application, you can easily take advantage of ObjectStore's 32-bit pointers in this 64-bit operating system environment by compiling with the -xtaso_short option. This option makes 32 bits the default pointer size and uses 64-bit pointers for particular declarations. The 32-bit pointer data type allows you to minimize the amount of memory used by dynamically allocated pointers, and assists in porting applications that contain assumptions about pointer sizes. See "Using the -xtaso option" for details about this option.
#pragma pointer_size directive
The #pragma pointer_size directive controls pointer size allocation for the following:
For this pragma statement to have any effect, specify -xtaso, -xtaso_short, -vptr_size, or -vptr_size_short on the cxx command.
This pragma statement has the following syntax:
#pragma pointer_size {long|64} #pragma pointer_size {short|32} #pragma pointer_size restore #pragma pointer_size saveThe #pragma syntax options are defined in the following table.
The save and restore options are particularly useful for specifying mixed pointer support and for protecting header files that interface to older objects. Objects compiled with multiple pointer size pragma statements are not compatible with old object files, and the compiler cannot detect that incompatible objects are being combined.
Using the -xtaso option
The -xtaso compiler option is useful when heterogeneity is not a consideration. Using -xtaso enables you to use the 32-bit pointer size only for selected pointers. The -vptr_size option makes 64 bits the default size of virtual function and virtual base pointers in a C++ class object (64 bits is the normal default). This -xtaso option also enables #pragma pointer_size and passes -taso to the linker.
#pragma pointer_size save #pragma required_vptr_size save #pragma pointer_size short #pragma required_vptr_size long class Table_Node { char *table; // 32 bit pointers Table_Node *next; Table_Node *(Table_Node::*search)(char *); // pointer to member has // 2 32 bit fields public: void insert_node(char *); Table_Node *extract_node(char *); Table_Node *search_forward(char *); Table_Node *search_backward(char *); }; #pragma pointer_size restore #pragma required_vptr_size restoreWhen you use this approach, it is important to specify the pointer size #pragma directives after any #include directives so the header files that assume 64-bit pointer sizes are not affected.
Use typedefs when building an application using the -xtaso option to avoid compilation errors that result from incompatible interface definitions. The following code example produces such a compilation error:
#include <ostore/ostore.hh> int main(int, char **) { os_int32 max_servers; os_server **servers; os_int32 n_servers; objectstore::get_all_servers(max_servers, servers, n_servers); } $ cxx example.cc -c -xtasoThe error message that results might look as follows:
example.cc:9: error: In this statement, the referenced type of the pointer value "servers" is "long pointer to os_server", which is not compatible with "short pointer to os_server". Compilation terminated with errors.The use of the typedefs enables the compiler to perform the correct pointer conversions to interface to the ObjectStore libraries. More precisely, the typedefs listed on the next page solve the situation of a compound pointer, that is, a pointer-to-a-pointer, which cannot be automatically converted by the compiler. The compiler automatically converts the pointer-to but does not convert what it points to, the a-pointer part.
An example of such a typedef is os_server_p. It is defined as an os_server*.
If you modify the example, replacing os_server **servers with os_server_p *servers, the program compiles cleanly:
#include <ostore/ostore.hh> int main(int, char **) { os_int32 max_servers; os_server_p *servers; os_int32 n_servers; objectstore::get_all_servers(max_servers, servers, n_servers); } $ cxx example.cc -c -xtasoNote that this affects C++ references as well as pointers.
The comprehensive list of typedefs supplied by the ObjectStore header files follows
Using the -xtaso_short option
The -xtaso_short option makes 32 bits the default pointer size. In this mode you need to use some mechanism to accommodate code that expects 64-bit pointers. If you select this method, remember that references to other libraries can be more complicated since any library with compound pointers requires you to use #pragmas. #pragmas and function declarations
In the default C++ installation, none of the system header files, including those for the standard C library, is protected, but see "Using the header file protection option" for an automated method of providing this protection. The alternative methods for doing this are to
#pragma pointer_size save #pragma pointer_size long extern "C" { int getrusage ( int who, struct rusage *r_usage ); } #pragma pointer_size restore
#pragma __environment save // Save pointer size #pragma __environment header_defaults // set to system defaults // existing header file #pragma__environment restore // Restore pointer size
For example, if the source code has #include <stdio.h>, the order of file processing would be
/usr/lib/cmplrs/cxx/protect_system_headers.shThis script creates, in all directories in a directory tree that contain header files, symbolic links to special header prologue and epilogue files.
The default directory tree root assumed by the script is /usr/include, but you can specify other roots.
No handler for exception: Miscellaneous ObjectStore error An inconsistency was detected during the allocation of an object of type part. The compiler believes the allocation size should be 40 bytes, while the schema believes it should be 32 bytes. Verify that the arguments to `new' match the type and/or array count of the object being allocated. (err_misc) Abort process (core dumped)
ossg -assf osschema.cc -asdb coll.adb -I/usr/local/ostore/4.0.0.C/ include schema.cc /usr/local/ostore/4.0.0.C/lib/liboscol.ldb <err-0004-0008> The following class definitions in library schema "/usr/local/ ostore/4.0.0.C/lib/liboscol.ldb" were inconsistent with the corresponding definitions obtained from other library or compilation schemas specified for building the application schema: "os_set" from the schema source file "/usr/local/ostore/4.0.0.C/ include/ostore/coll/coll_int.hh" the class size changed from 24 to 40 "os_tinyarray" from the schema source file "/usr/local/ ostore/4.0.0.C/include/ostore/coll/query.hh"... *** Exit 1 Stop.
No handler for exception: Attempt to call virtual function without vtbl. Vtbl for type os_packed_list not linked into application. (err_missing_vtbl) IOT trap (core dumped)Here is an example of an HP makefile link command line:
$(CCC) +eh -Wl,-E -g -o test test.o os_schema.o $(LDLIBS)
Note that HP recommends that you use extensions consisting only of .c or .C without additional characters, because while the compiler accepts the additional characters, other HP tools and environments might not.
If you compile only, each C++ source file produces an object file whose prefix is identical to the source file but with a .o suffix. However, if you compile and link a single source file into an executable program in one step, the .o file is automatically deleted.
CC: "myprog.C", line 82: warning: debug.object_ids: weird vtable->vclass for os_Collection <const MyObject*> (198) CC: "myprog.C", line 8: warning: debug.emit_variable: bad address found for name ABC::xyz::ex (251)Also, you might see these warnings during the link phase:
pxdb: [cu: 0 index: 0x136] can't link template/expansion pxdb: [cu: 0 index: 0x14f] can't link template/expansion pxdb: [cu: 0 index: 0x168] can't link template/expansion pxdb: [cu: 0 index: 0x181] can't link template/expansionYou might see the following warnings during compilation of a source file that uses stack transactions (that is, that contains OS_BEGIN_TXN/OS_END_TXN macros):
CC: "myprog.cc", line 342: warning: label in block with destructors (2048)Such warnings, where they concern the stack transaction macros, can safely be ignored.
delete [] persistent_array;Without -vdelx, the compiler generates a direct call to the Sun vector delete routine. This routine returns an error message indicating that it did not allocate the array:
error: delete [] does not correspond to any \Qnew'If you use CC to link (by means of ld), then the linker receives the correct libraries. Be sure to study the CC and ld man pages for details, especially if you invoke ld directly.
On Solaris 2.x systems, you must compile (and link) ObjectStore applications with real thread support. Specify -losthr on the link line to supply the proper library for real thread support. The libosths library, a stub threads library, can also be used with Solaris 2.x systems. Using this library can result in higher performance in some circumstances because it turns off thread locking.
On Solaris 2.x, you must always specify the -mt compiler option on the CC command line. This is required for a successful compilation.
CC -mt -I$(OS_ROOTDIR)/include $(CCFLAGS) -o foo -L$(OS_ROOTDIR)/lib -los -losthrNote that to link an application to use threads,
CC -I$(OS_ROOTDIR)/include $(CCFLAGS) -o foo -L$(OS_ROOTDIR)/lib -los -losthsNote that to link an application that does not use threads,
In an ObjectStore makefile, in the LDLIBS line, you must specify each library with which you are linking.
Then, in the line of the makefile where ossg generates the application schema, you must specify the library schemas needed by your application schema. For each library schema that you specify in the ossg command line, you must specify the corresponding library in the LDLIBS line.
Note that the reverse is not true. For each library that you specify in the LDLIBS line, you do not necessarily specify a library schema in the ossg command line. This is because every library does not necessarily have a library schema. Only those libraries that store or retrieve persistent data have associated library schemas.
Tabs and spaces
If you are using an on-line version of this book, and you copy a makefile and try to use it, make sure that there are tabs and not spaces at the beginning of relevant lines. Application schema database
In makefiles, you should not specify an existing ObjectStore database as the application schema database. Doing so can corrupt your build process if the Server log has not been propagated to the database. Makefile template
include $(OS_ROOTDIR)/etc/ostore.lib.mk APPLICATION_SCHEMA_PATH= app-schema-db LDLIBS = $(OS_EXPORT) -losqry -loscol -los -losths [ other libraries] SOURCES = .cc files OBJECTS = .o files EXECUTABLES = executables CCC=CC all: ${EXECUTABLES} executable: $(OBJECTS) os_schema.o $(CCC) -o executable $(OBJECTS) os_schema.o \ $(LDLIBS) $(OS_POSTLINK) executable .o files: .cc f iles ${CCC} $(CPPFLAGS) -c .cc files os_schema.o: os_schema.cc $(CCC) $(CPPFLAGS) -c os_schema.cc os_schema.cc: schema.cc
ossg -assf os_schema.cc -asdb $(APPLICATION_SCHEMA_ PATH) \ $(CPPFLAGS) schema.cc $(OS_ROOTDIR)/lib/libosqry.ldb \ $(OS_ROOTDIR)/lib/liboscol.ldb clean: osrm -f ${APPLICATION_SCHEMA_PATH} rm -f ${EXECUTABLES} ${OBJECTS} os_schema.*
These handlers are critical to ObjectStore's operation. If your application disturbs them, it will fail, and it might fail in a way that makes it difficult to determine why it failed.
If you must temporarily change the state of the handler for SIGSEGV and SIGBUS, be sure to save and restore the complete state. You cannot do this with the signal entry point; you must call sigaction and save the contents of the structure returned as the old handler state.
all: my_exec my_exec: main.o os_schema.o foo.o bar.o CC -o my_exec main.o os_schema.o foo.o bar.o -los $(OS_POSTLINK) my_exec my_exec.cdb:: schema_source1.o ossg -csdb my_exec.cdb $(CPPFLAGS) schema_source1.cc touch schema_source1.o my_exec.cdb:: schema_source2.o ossg -csdb my_exec.cdb $(CPPFLAGS) schema_source2.cc touch schema_source2.o os_schema.cc: my_exec.cdb ossg -asdb my_exec.adb -assf os_schema.cc my_exec.cdbFor more information, see Generating a Compilation Schema.
Establishing Fault Handlers in POSIX Thread Environments
On some UNIX systems, the POSIX thread environment gives each thread its own set of UNIX signal handlers. On such systems, the ObjectStore handlers for SIGSEGV (and in some cases SIGBUS) must be established in each thread.
A typical function that uses these macros in an ObjectStore application would look like this:
void thread_1( ) { OS_ESTABLISH_FAULT_HANDLER ... your code... OS_END_FAULT_HANDLER return value; }
You can benefit from using these macros, even on platforms not requiring them. This practice helps ensure portability of code, and also guards against potential problems resulting from future changes to your operating system.
When ObjectStore is fully initialized, it examines each of the shared libraries specified at link time that was opened by shl_load or cxxshl_load. ObjectStore searches the shared libraries for the symbols that identify the tables in the schema object file. After it finds these symbols, it searches again to find as many vtbls and discriminants as it can.
z 10 irs z 11 irs
ignore 10 ignore 11
ignore SEGVIt is not necessary to ignore SIGBUS.
/usr/include/stddef.h line 30: syntax error on input" (103)
Note that you must use the 32-bit edition of Visual C++.
On Windows platforms, the only ObjectStore library is ostore.lib. You must link with this library every time you build an ObjectStore application.
Ensure That You Include Required Files
The ObjectStore installation program modifies your INCLUDE environment variable to include the %OS_ROOTDIR%\include directory. Therefore, under normal circumstances, you should not need to specify this directory in a compilation command.
-I%OS_ROOTDIR%\includeIf you include in your makefiles the makefile shipped with ObjectStore, %OS_ROOTDIR%\etc\ostore.mak, you can use the makefile macro COMPILER_OPTS to get the proper compilation options.
mycode.obj: mycode.cpp cl -c -W3 -EHa -G4 -D_X86_=1 -DWIN32 -MD -Zi -vmg -vmv\ I$(OS_ROOTDIR)\include mycode.cpp
The option -MD is required in order for you to use msvcrt.lib, which is required by ObjectStore.
The implementation of TIX exceptions depends on C++ exceptions. All ObjectStore modules should be compiled with the /EHa option. ObjectStore header files that rely on C++ exception handling use a pragma statement to ensure that /EHa is used. If you do not specify /EHa when you compile files that use those headers, you receive an error such as
osdraw.cpp(168) : error C4530: C++ exception handler used, but unwind semantics are not enabled. Specify -EHaDo not ignore this error.
The option -Zi causes debugging information to be put in the project database. You can also use the -Z7 or -Zd option.
All compiler and linker options not mentioned explicitly can be set as you want.
ObjectStore is linked with msvcrt.lib, which allows ObjectStore to freely allocate objects in any ObjectStore DLL and deallocate them in any other ObjectStore DLL. This is because all ObjectStore DLLs share the single allocator in MSVCRT40.DLL.
Because ObjectStore is linked with msvcrt.lib, it is easy for most applications that also link with msvcrt.lib to deallocate objects that are allocated by ObjectStore APIs (for example, os_collection::query()).
You can use a library DLL that is not compiled with the -MD option. Keep in mind that it has a separate copy of the C run-time library and therefore you cannot share certain objects between that DLL and the rest of the application.
If you must link with LIBC.LIB or LIBCMT.LIB, you can do one of two things:
Linking an executable file would look like this:
link @<< -NODEFAULTLIB -machine:i386 -subsystem:windows -debugLinking a DLL would look like this:
-debug-type:cv -out:myapp.exe myapp.obj myschema.obj ostore.lib msvcrt.lib kernel32.lib user32.lib gdi32.lib winspool.lib <<
link @<< -NODEFAULTLIB -dll -machine:i386 -debug -debugtype:cv -out:myapp.dll myapp.obj myschema.obj ostore.lib msvcrt.lib kernel32.lib user32.lib gdi32.lib winspool.lib <<myschema.obj in the previous two link commands is the application schema object file output from the schema generator (ossg).
In both examples, the %OS_ROOTDIR%\lib directory must be listed in your LIB environment variable. This is normally set up by the ObjectStore installation program.
The schema generator (ossg) is a C++ compiler front end that parses C++ source code to obtain information. This means that you must pass the same compiler flags to ossg as you pass to the compiler when you are compiling your source. It is especially important to duplicate the -I, -D, and -Zp arguments. Also, remember that -MD implies -D_DLL, so pass the -D_DLL to ossg. Note how $(COMPILER_OPTS) is used for both compilation and schema generation in the following makefile fragment.
!include $(OS_ROOTDIR)\etc\ostore.mak OBJECTS=note.obj EXECUTABLES=note.exe APPLICATION_SCHEMA_PATH=note.adb all: $(EXECUTABLES) myschema.obj: schema.cc ossg -asof myschema.obj -asdb $(APPLICATION_SCHEMA_ PATH) \ $(COMPILER_OPTS) schema.cc note.obj: note.cc $(COMPILER) $(COMPILER_OPTS) note.cc note.exe: $(OBJECTS) myschema.obj $(CL_LINK) /OUT:note.exe $(OBJECTS) myschema.obj \ $(OS_ROOTDIR)\lib\ostore.lib clean: -osrm -f $(APPLICATION_SCHEMA_PATH) -del $(OBJECTS) osschema.*
!include $(OS_ROOTDIR)\etc\ostore.mak OBJECTS=note.obj EXECUTABLES=note.exe APPLICATION_SCHEMA_PATH=note.adb all: $(EXECUTABLES) myschema.obj: schema.cc ossg -asof myschema.obj -asdb $(APPLICATION_SCHEMA_ PATH) \ $(COMPILER_OPTS) schema.cc \ $(OS_ ROOTDIR)\lib\osquery.ldb \1 $(OS_ROOTDIR)\lib\os_coll.ldb2 note.obj: note.cc $(COMPILER) $(COMPILER_OPTS) note.cc note.exe: $(OBJECTS) myschema.obj $(CL_LINK) /OUT:note.exe $(OBJECTS) myschema.obj \ $(OS_ROOTDIR)\lib\ostore.lib clean: -osrm -f $(APPLICATION_SCHEMA_PATH) -del $(OBJECTS) osschema.*
2Add collections library schema.
Specifying Environment Variables
The following environment variables are automatically set by the ObjectStore installation program:
You can edit these environment variables using the Control Panel System applet.
Debugging Your Application
Visual C++ debugger
ObjectStore handles all access violations to determine if they are persistent memory accesses. If you handle access violations in the Visual C++ debugger you would disrupt this, so leave this exception unhandled in the debugger. You might see multiple exception messages such as the following:
First-Chance Exception in yourprog.exe: 0xC0000005: Access Violation. First-Chance Exception in yourprog.exe: ( something.DLL) 0xC0000005: Access Violation.You can safely ignore these messages.
Under Debug | Exceptions, the default for exception C0000005 Access Violation is Stop if not handled. Do not change this to Stop Always. If you do, ObjectStore cannot function normally.
The debug DLLs are available on the distribution CDROM.
To obtain a back trace using the debug DLLs, put the debug DLL directory in the front of the path environment and then run the msvc debugger.
For example, using myapps on drive C and a CDROM on drive E, you would issue the following commands:
C:\myapps> set path = e:\windows\debnt\bin;%path% C:\myapps> start msvc myapps.exe
#include <iostream.h> #include <ostore/ostore.hh> void break_hook(tix_exception *err, os_int32, char* message){ cout << "Set break point here" << endl; cout << "Have a look at the stack " << endl; // You may also want to put up a message box that displays // the contents of the message parameter. } main(int argc, char *argv[]) { OS_ESTABLISH_FAULT_HANDLER os_database *db1; objectstore::initialize(); tix_exception::set_unhandled_exception_hook(break_hook); do_something_fun(); OS_END_FAULT_HANDLER }
To do this, add the following to stdafx.h after including ostore.hh and afxwin.h:
// If we let DEBUG_NEW keep the definition that it's given in // afxwin.h, // and let the "#define new DEBUG_NEW" from afx.h stay, then our // overloadings of new won't be recognized by the compiler. #ifndef _AFX_NO_DEBUG_CRT #ifdef DEBUG_NEW #undef DEBUG_NEW #define DEBUG_NEW new #endif #ifdef new #undef new #define new new #endif #endifThen, add the following at the end of stdafx.h:
// This declaration taken from ostore.h */ extern "C" void _OSSYSCALL objectstore_delete(void *); // In DEBUG mode, MFC has its own operator delete. We need to get // first dibs on the deletion if the thing being deleted is persistent. // #if defined(_DEBUG) && !defined(_AFX_NO_DEBUG_CRT) inline void operator delete(void* p) { objectstore_delete(p); } #endif
Class os_CString
ObjectStore provides a shadow class of CString called os_CString that does the job of storing CString objects persistently. These classes can be used interchangeably for most purposes. Generating MFC Applications Using ObjectStore AppWizards
ObjectStore includes a custom AppWizard for VC++ 5.0. This wizard can be used to generate MFC applications that use ObjectStore.
The source code for the ObjectStore AppWizard can be found in the directory %OS_ROOTDIR%\examples\ostoreaw.
You must add OS_ESTABLISH_FAULT_HANDLER to the top-level threads functions when using threads.
ossg < other ossg args> schema.osgThe ObjectStore MFC example is set up to use this technique.
In the directory %OS_ROOTDIR%\examples\dll, there are two subdirectories, LIBSCHM and NOSCHM. These two directories demonstrate two ways to use ObjectStore from within a DLL.
Each of these two directories contains two subdirectories, PROG and LIB. The LIB directory creates a DLL called people.dll that uses ObjectStore. The PROG directory creates a program that uses people.dll.
The difference between the directories LIBSCHM and NOSCHM is as follows:
Building Applications on Machines Remote from the Server
You can build an application on a machine that is remote from the ObjectStore Server. Example 1
ossg -asdb foo:c:\appdir\appschema.adb -assf osschema.cc / -cd schmdefs.hh myschema foo:c:\ostore\lib\os_coll.ldbThis example assumes that
If you can use Windows networking to connect to a network drive on the Server, you can use pathnames that start with that network drive letter.
nfs use x: bar:/usrThis mounts the /usr file system of a remote Server machine called bar on the local directory x. Having done that, you use the following form for your ossg command line:
ossg -asdb x:\appdir\appschema.adb -assf osschema.cc \ -cd schmdefs.hh myschema.cc x:\ostore\lib\os_coll.ldb \ x:\ostore\lib\os_query.ldbThis example assumes that
Therefore, every ObjectStore application must put a handler for access violations at the top of every stack in the program. This normally means putting a handler in a program's main or WinMain function and, if the program uses multiple threads, putting a handler in the first function of each new thread.
ObjectStore provides two macros to use in establishing a fault handler:
int main (int argc, char** argv) { OS_ESTABLISH_FAULT_HANDLER ... your code... OS_END_FAULT_HANDLER return value; }A WinMain function would also look like the preceding example.
objectstore::initialize() need only be called once, even though an application has multiple threads.
c:\ostore\include\ostore\mop.hh(1041) : warning C4069: long double is the same precision as doubleTo avoid these warnings, ObjectStore header files use pragma statements that disable them. You can enable this warning for your code by adding the following after the ObjectStore include files:
#pragma warning ( default : 4069 )
pkunzip -d debug.zip
To use the ddebug build, install the ddebug libraries as directed in Installing DEBUG.ZIP or DDEBUG.ZIP. Then compile your application using the /MDd switch. Using Project | Settings in Developer Studio, select C/C++, Category Code Generation, Use runtime library Debug Multithreaded DLL. This automatically selects ostored.lib as a default library. To run the resulting application, ensure that the ddebug build is in your PATH.
The following table compares the features of retail ObjectStore, debug, and ddebug:
Characteristic | Retail | debug | ddebug |
---|---|---|---|
Installation with INSTALL? | Yes | No | No |
Optimized? | Yes | No | Yes |
ObjectStore symbols available? | No | Yes | Yes |
Drop-in capability? | Yes | Yes | No |
Compiling and linking applications
Use the following information when compiling and linking applications:
* The /MDd option defines the symbol _DEBUG, which determines the link library used by ObjectStore.
OS/2
This section provides information about compiling and linking ObjectStore applications using the VisualAge C++ compiler, icc, on OS/2. Using Compiler Options
Required
You must always use these compiler options:
/Gd | Dynamically link run-time library |
/Gm | Multithreaded libraries |
Prohibited
You cannot use these compiler options with ObjectStore:
/Gr | Device driver |
/Rn | Subsystem environment |
You cannot use these compiler options when compiling code that includes ObjectStore header files:
/EHa | No exception support |
/H | Short external names |
/Ms | Use _System calling sequence |
/Sc | Use cfront language standard |
/Sg | Set margins |
/Sp | Pack structures |
/Sq | Use sequence numbers |
Specifying default language for files
Use /Tdp to compile all source and unrecognized files that follow on the command line as C++ files. You can specify /Td anywhere on the command line to return to the default rules for the files that follow it. No rules
There are no rules for compiler and linker options not explicitly mentioned. You can decide how to set them. Linking Your Files
After you generate the application schema, you can link your application object files, ObjectStore libraries, and the application schema object file into an executable. Required library
You must link ObjectStore applications with the library ostore.lib. To do so, you can either add %OS_ROOTDIR%\lib to your LIB environment variable and put ostore.lib on the link command line, or you can put %OS_ROOTDIR%\lib\ostore.lib on the link command line. Case sensitivity
ObjectStore applications run correctly whether or not linking is case sensitive. Object Design recommends case-sensitive linking. Compiling the application schema source file
You must compile the application schema source file produced by ossg into an object file. This file includes ObjectStore header files and none of your header files, so the compilation command line is simple. For example:
icc /C /Gd /Gm myschema.cppThis produces a file named myschema.obj.
icc /Tdp /B"STACK:32768" /Femy_exec.exe myschema.obj \ my_ ob1.obj my_ob2.obj %OS_ROOTDIR%\lib\ostore.lib
myschema.obj: myschema.cpp ossg -assf myschema.cpp -cd schmdefs.hh -asdb myschema.adb \ myschema $(OS_ROOTDIR)\lib\os_coll.ldb icc /C /Gd /Gm myschema.cpp my_exec.exe: my_exec.obj myschema.obj icc /Tdp /B"STACK:32768" /Femy_exec.exe my_exec.obj \ myschema.obj $(OS_ROOTDIR)\lib\ostore.lib
OBJECTS=note.obj EXECUTABLES=note.exe APPLICATION_SCHEMA_PATH=note.adb all: $(EXECUTABLES) myschema.obj: myschema.cc icc /C /Gd /Gm /Ti myschema.cc myschema.cc: schema.cc ossg -assf myschema.cc -cd schmdefs.hh \ -asdb $(APPLICATION_SCHEMA_PATH) \ $(CPPFLAGS) schema.cc note.obj: note.cc icc /C /Gd /Gm /Ti note.cc note.exe: $(OBJECTS) myschema.obj icc /Tdp /B"STACK:32768" /Fenote.exe $(OBJECTS) myschema.obj \ $(OS_ROOTDIR)\lib\ostore.lib clean: -osrm -f $(APPLICATION_SCHEMA_PATH) -del $(OBJECTS) osschema.*
OBJECTS=note.obj EXECUTABLES=note.exe APPLICATION_SCHEMA_PATH=note.adb all: $(EXECUTABLES) myschema.obj: myschema.cc icc /C /Gd /Gm /Ti myschema.cc myschema.cc: schema.cc ossg -assf myschema.cc -cd schmdefs.hh \ -asdb $(APPLICATION_SCHEMA_PATH) \ $(CPPFLAGS) schema.cc \
$(OS_ROOTDIR)\lib\osquery.ldb \ $(OS_ROOTDIR)\lib\os_coll.ldb note.obj: note.cc icc /C /Gd /Gm /Ti note.cc note.exe: $(OBJECTS) myschema.obj icc /Tdp /B"STACK:32768" /Fenote.exe $(OBJECTS) myschema.obj \ $(OS_ROOTDIR)\lib\ostore.lib clean: -osrm -f $(APPLICATION_SCHEMA_PATH) -del $(OBJECTS) osschema.*
You can do this by using the OS/2 environment variable PMDEXCEPT. When this environment variable is set to 1, the debugger unconditionally passes ObjectStore exceptions to ObjectStore.
However, if your application fails with a general protection fault, setting PMDEXCEPT causes the program to exit before you can debug the error.
If you need to debug this kind of problem, set a breakpoint on the first instruction in O4LOW.DLL. This breakpoint occurs only if there is a general protection fault that ObjectStore declines to handle (such as dereferencing a null pointer).
To obtain a back trace using the debug DLLs, put the debug DLL directory in the front of the LIBPATH environment, reboot, and then run the IPMD debugger.
All databases, including application schemas and library schemas, must physically reside on the same machine as the Server. The schema generator expects to be able to connect to a Server and produces an error message if it cannot do so. Consequently, you must provide the schema generator with a Server-relative pathname. There are two ways to do this.
You can specify ObjectStore Server-relative pathnames even if you are not using NFS or another file sharing option. This does not rely on any file system protocol. Instead, this syntax is recognized by ObjectStore tools. Using Server-relative pathnames, the ossg command line would look like this:
ossg -asdb foo:c:\appdir\appschema.adb -assf osschema.cc / -cd schmdefs.hh myschema foo:c:\ostore\lib\os_coll.ldbThis example assumes that
mount x: foo:c:\This mounts the C drive of a remote Server machine called foo on the local directory x. Having done that, you use the following form for your ossg command line:
ossg -asdb x:\appdir\appschema.adb -assf osschema.cc \ -cd schmdefs.hh myschema.cc x:\ostore\lib\os_coll.ldb \ x:\ostore\lib\os_query.ldbThe same assumptions apply here as in the previous example.
Updated: 03/26/98 19:59:13