QNX Programming Tips
PhAB Interface
- Some widgets are not easy to see, let alone select, when
placed in a container (e.g. a PtTimer in a PtWindow). To select
them, use the Module Tree (underneath Callbacks) tab in
the Control Panel, or press F9 and F10 to cycle through all the
widgets.
- Dropping a widget onto a PtPane makes the widget a child of
the pane automatically.
- When adding an additional callback to an event, take care to
select the "NEW" item before proceeding. By default, the first
callback in the list is selected - if you click one of callback
types buttons (e.g. "Dialog"), it will remove the selected
callback without warning.
- When creating module callbacks, it is possible to select a
setup function for the module as part of the module callback.
However, it may be better to link the setup function to one of
the module's own initial events. This is more modular in that the
setup function remains associated with the module, even if the
link is removed.
- When selecting callbacks, PhAB provides a drop-down list of
"compatible" callbacks. However, I have found that this list does
not contain all available callbacks (e.g. callback functions that
were once linked, but have since been removed, whilst their code
remains. I have found that PhAB links them correctly if their
name is types in the box, and have not encountered any
compatibility problems.
- To have PhAB invoke graphical gvim, rather than console-based
vim, go to Options, then Preferences, and add "gvim" (without the
quotes) in the "Edit Command" field, and ensure the "No Shell"
check-box is checked.
Debugging
- To include debug information in the executable, select
Debug in the Version box.
- When developing prototypes, it is helpful to have the program
output test messages in strategic places. For instance, if a
function called
GetTemperatureData
seems not to be
doing any work, we can confirm it is actually entered by putting
a simple printf("TRACE: GetTemperatureData
entered\n")
at the start of the function. However, in a
Photon application, it's not easy to see standard output messages
since there may not be a text terminal to display them in. This
can be resolved by directing the diagnostic printfs to STDERR,
and putting the text 2> errlog.tmp in the Run
arguments box. This redirects STDERR to a file called
errlog.tmp, which will be created in the
platform-specific directory.
Source-Code File Management
Compiling
- Two or more Makefiles are used during a build. The first is
in the src/ directory within the application directory;
this is the Makefile that is called by PhAB and Make. The first
Makefile looks for and calls the Makefile in the
platform-dependent directories.
- To be on the safe side when developing new software, tell the
compiler (GNU gcc, via QNX's front-end qcc) to show all
compilation warnings. This is achieved by modifying the
platform-dependent Makefiles. Find the line
CC = qcc
and append -Wall
to it.
- The preconfigured make options are:
- shr: builds executables that use shared libraries.
- app: builds standalone executables.
- clean: deletes the application's binary files.
- install: copies the executable to
/usr/photon/bin/
- proto: generates prototypes for your routines and puts
them in proto.h
- After changing the value of some resource in PhAB, you don't
need to regenerate, but you do need to recompile.
Editing
- Do you want to modify the code template that Photon uses,
such as when you create callback functions? If so, you can modify
the file, although you'll have to overcome its write-protection
(perhaps get root privileges) first. You can find the file at
usr/photon/appbuilder/codelib/stubfun.c. If you mess it
up, you can find a backup at
pkgs/repository/qnx/ph/devtools-2.0.2/usr/photon/appbuilder/codelib/stubfun.c
although your version number may be different.
- If you want vim to highlight QNX type identifiers (denoted by
having "_t" on the end), and constant identifiers (prefixed with
"Pt_"), create a directory thus mkdir
~/.vim/after/syntax/ and make a file called c.vim.
In this file, create the following two lines:
syntax match
cType /[^ (]*_t[ )]/
and syntax match cConstant
/Pt_[^ )]*/
. This is not an ideal solution, since it may
match some items that are not types; the best but verbose
solution is to include each individual type name.
- Vim's own syntax files can be found at
/usr/local/share/vim/vim56/syntax/c.vim for the default
QNX 6.1 installation, or
/usr/share/vim/vim60/syntax/c.vim.
Photon Programming
- Warning: PtSetResource cannot be used in the initialisation
function (specified in the Application | Startup Info/Modules...
dialog box), since the widget it refers to does not yet exist.
The program will crash immediately without even drawing the
opening window.
- The sequence of events triggered when the base window opens
is Opening, Realised, GotFocus. I am not sure when Activate and
Arm are triggered. If you have a single button in the window, the
event sequence is (if you don't click on anything) Window
Opening, Button Realised, Window Realised, Button GotFocus,
Window GotFocus. If the button is clicked, Button Arm and Button
Activate are generated, in that order.
- The size of a window cannot be detected in code (say by a
GetResource()
call in one of its opening callbacks)
until the GotFocus event occurs. This is especially
problematic if you set the "Window State" property to
"Ph_WM_STATE_ISMAX" — in this case, the size of the window
will be reported as being the same as it was in the PhAB
environment, rather than it's maximised size. It will only return
the correct (maximised in this case) value after the GotFocus
event. If you want to position child widgets of the window, it
should be done in the GotFocus window. However, this event may be
generated many times during a window's lifetime, so use a flag to
ensure that the child-positioning code is run only once, during
the first call of the GotFocus callback.
- In the "Build & Run" dialog box, there is an option
called "Action". The options here are "Shared" "Static",and
"Clean". Shared tells make to generate an executable that uses
shared libraries. Static tells make to generate a stand-alone
executable with all the required code built-in. Clean tells make
to delete all object (*.o), error (*.err), and
map (*.map) files, along with the executable file for
this application. For some reason I can't work out, the make
option selector in PhAB does not include the "proto" and
"install" options. However, make seems to be first invoked
automatically with the "proto" option when the "Static" and
"Shared" options are invoked.
- To add a use message to the executable generated by make,
place the text in a file called Usemsg in the main
application folder (the level above the src/ folder. Use
messages can be added manually with the usemsg command.
- Normally, PhAB does a good job of telling make which files to
include in a build. However, when creating callback functions for
dynamically created widgets in their own source files, PhAB does
not know about these source files. They can be added manually by
editting indSfiles and indHfiles.
indSfiles contains the
MYSRC
variable; add
your .c source files that PhAB doesn't know about to this
variable. Ensure you give them a directory location relative to
the Makefile that will actually be using them. For instance, if
your source files are in the src/ directory, and you are
compiling only for the x86 platform, the Makefile that calls the
source files is in the gcc_ntox86/ directory so you
should put ../before each of the source filenames in
indSfiles. indHfiles should contain your header files
that PhAB doesn't know about, and is only used for the "proto"
make option. See the help document
Generating, Compiling, and Running Code for more
information.
- If you create a widget in code (rather than adding it in
PhAB) in one source file, and place the callback function in a
different source file, this can give rise to some make errors. I
got caught out with the following mistakes:
- Do not #include the callback's source file in the
widget-creation source file. The function prototype will be
obtained automatically from proto.h.
- I did think it was necessary to place a
#include
"globals.h"
at the top of proto.h so that
any user defined types in the prototypes will be
recognised. I had loads of "Parse error before" error
messages when I didn't, but somehow the errrors stopped
even when I took the include out, so I'm still
investigating this.
- Parse errors in proto.h are often caused by types
that are undefined when the compiler reaches the type's first
appearance. Such types may be user-defined types or may be QNX
types that are not defined by default (e.g. RtTimer_t). To avoid
these errors, place the uder-defined types in globals.h,
or #include the files that contain the type definitions in
globals.h. Thanks to Wojtek Lerch for this fix. Note
that in this case, #include globals.h must come before
#include proto.h
- When converting a function that was called as a callback,
registered with Photon, to an ordinary function called from some
other part of the program, you must make a number of obvious, and
not-so-obvious, changes: remove the "avoid-unwanted-references"
line, remove the parameters, change the function return type,
remove or change the function return value, add the
filename.c to indSfiles and filename.o
to indOfiles.
- The Helpviewer files are stored in directories (based on the
product names) in /usr/help/product/.
Content last updated: 2004-04-19