miser

oMiser Technical Note m110400
oMiser Objects (MOb) Directory
MOb API
orcmid.github.io>

miser> oMiser>


m110400c>

0.1.2 2026-03-15T19:19Z

The MOb provides access to identifiable obs, whether intrinsic primitives, ones introduced as lindies, binding-name values, or derived individuals (synthetics) produced by applicative-operation extensions.

1. Establishing oMiser and the MOb

The initialization of an oMiser instance involves establishment of the initial MOb. This is accomplished with the omEstablish procedure,

HRESULT omEstablish( const CLSID* omClassID,   // a supported oMiser class
                       const IID* riid,        // IUknown or IMOb
                           void** ppvObject    // returned interface pointer
                     );

defined in the oMiser header files oMiser-Win32.h and oMiser-Win32.hpp for C and C++, respectively. This is the oMiser-specialized counterpart of a COM class factory for the MOb.

The supported omClassID values are defined in the header files for the current oMiser version. The practice is to support earlier Class IDs until breaking changes make that infeasible.

The riid parameter must be for IUnknown or IMOb.

2. Simplified Interfaces

An established MOb permits simplified interface helpers because there is always one and only one established MOb. This allows helper operations with simplified parameters. For example,

HRESULT omGetLindy(const char[] id, void **ppvIob);

Is a friendlier version of the C Language

HRESULT ppvIMOb->pv->GetLindy(ppvIMOb, const char[] id, void **ppvIob);

and the equivalent C++ Language

HRESULT ppvIMOb->GetLindy(const char[] id, void **ppvIob)

where, in the friendly case, a ppvIMOb is held privately and usable by the set of friendly versions automatically. The friendly versions are the same for both C and C++. The results are still COM Interface pointers, but for Iob interfaces.

There is an additional HRESULT defined for there having been no successful omEstablish before a friendly operation is attempted.

3. Strings vs. BSTR

Officially, strings of characters must be in BSTR (Unicode UTF16-LE) form for correct use in COM interfaces. The difficulty of BSTR for oMiser is with the high incidence of wide (16-bit) character codes with many 0 bits. This does not work well for hashing of identifiers.

UTF8 strings are used in the oMiser API to facilitate hashing and also economize on storage in US and Western European settings. The trade-off will be reviewed after there is more experience and good statistics between UTF8 and UTF16-LE (BSTR) coding of identifiers used with oMiser and oFrugal.

In the determination of identifier length, each code point, regardless of its length in UTF-8, counts as one character. Whether the Standard C Language allowance for identifiers of up to 63 characters is tolerated, the practice of truncating longer identifiers, if implemented, will lead to oMiser warnings.

It might also be possible to adjust hashing to deal with a high incident of recurring 0x0 and similar bytes and even neutralize identifier hashes by having them always conducted on UTF-32 code points. That is very speculative for now.

4. oFrugal Decoupling

Although the primary oMiser application is oFrugal, the API is simplified by not enforcing any particular constraints that should, ideally, be handled by the application, whether oFrugal or another usage.

Applications, including oFrugal, are expected to filter and correct the identifiers they employ. For example, for omGetPrimitive it is up to the application to include the leading “.” and capitalize the primitive name (e.g., .ARG instead of .arg or any other mixing of cases). There are similar considerations with respect to binding names. Inclusion of the ^ prefix is valuable to avoid collisions with lindies (which result in errors if either conflict) but oMiser does not fully verify identifier syntax.

This absence of defensive operation is intended to decouple from oFrugal specifically and also leave checking to the application level and not have potential duplication at the oMiser level. This approach is amenable to reconsideration, since the MOb API is not performance critical as much as with the Iob interface and operations.

5. The Friendly API

HRESULT omGetPrimitive(const char[] id, void **ppvIob);
        // return the primative individual for the specified .-prefixed
        // id string.  If there is no such individual, a ?.-form lindy
        // is the result and the HRESULT is an exception success value.
        // The severity with which that HRESULT is treated is a matter for
        // the application.

HRESULT omGetLindy(const char[] id, void **ppvIob);
        // return the lindy individual for the specified lindy id.
        // If there is a conflicting non-lindy named entry, the conflict
        // will be reported as a failure.  If there is no entry,
        // one will be created.

HRESULT omSetBinding(const char[] id, const void *pvIob);
        // set the identified binding to have the supplied object as
        // the binding value.  It is recommended to use a distinct
        // prefix, such as oFrugal's '^', to avoid conflict with lindies.
        // If there is a conflict with an used identifier that is not
        // for a binding, a failure result is returned and the binding
        // is not established/updated.

HRESULT omGetBinding(const char[] id, void **ppvIob);
        // return the value defined for the identified binding.  If
        // there is no such binding, NULL is returned and an error
        // HRESULT reported.

HRESULT omGetVersion(int semver[3])
        // return a semantic version major, minor, patch triple value for the
        // version of oMiser being operated.  There is no semver suffix
        // provision.

size_t omGetTitle_s(char szTitle[], size_t maxTitle);
        // deliver a descriptive title to the szTitle[] array, not exceeding
        // maxTitle chars including the terminal '\0'.  A typical title
        // is "oMiser 0.0.0 (spitball)".  The number of chars transferred
        // is returned.  Titles taking more than maxTitle chars will be
        // truncated to maxTitle chars, including a final '\0'.
        // A result of 0 indicates that no transfer occured and there may
        // be a defect in the parameters.

6. Lifecycle Management

It must be understood that, even with friendly API operations, the pvIob and ppvIob parameters are all for COM interface pointers.

Successfully returned pointers into a ppvIob variable are counted as a reference and that reference must be managed by the application in accordance with COM conventions.

Successfully-accepted pvIob pointers will have a reference managed by the MOb but with no presumption about the references held by the application. If a binding is replaced, the previously-bound interface reference held by the MOb will be released.

The friendly API does not provide any versioning adjustments and any defense against disparities between supported riids and the ones assumed in the friendly API implementation versus the linked oMiser code. Unfriendly HRESULTs can arise, depending on how application build processes are kept in step with supported oMiser releases.


I invite discussion about Miser Project topics in the Discussion section. Improvements and removal of defects in this particular documentation can be reported and addressed in the Issues section. There are also relevant projects from time to time.

Hard Hat Area You are navigating the Miser Project on Github

created 2026-02-25 by orcmid