473,785 Members | 2,784 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

A design problem: how to represent resource id's

[I'm cross-posting to comp.lang.c++ since any solution is constrained by
that language, i.e. this is much about how to use that language]

<what to design a C++ solution for>
A Windows API /resource/ is data embedded in the executable, accessed
via API functions. A resource is completely identified by the quadruple
(id, type, language, file), where (1) id is what, for want of a better
name, I'll call a /kludgeon/, (2) type is also a kludgeon, (3) language
is a small integer identifying a concrete national language or one of a
set of pseudo-languages such as the Windows installation's language or
the language implied by the locale associated with the execution thread,
or it is an empty specification, resulting in the API level's
unspecified best match with the thread locale's implied language, and
(4) file is the executable file or DLL the resource resides in.

A kludgeon, used for id and type, can be a 16-bit integer or a general
identifier represented as a string. Vis-a-vis API functions it must be
specified as (1a) a pointer to a general identifier string, or (1b) a
pointer to a string of the form "#1234" for integer id 1234, or (1c) a
pseudo-pointer with all bits zero except the 16 least significant bits,
which then specify an integer kludgeon. An API function kludgeon
argument is typewise just a pointer to char or wchar_t (call that TChar
for simplicity, i.e., argument type TChar const*), and accepts any of
the forms (1a), (1b) and (1c) -- the latter being most efficient.

For naming kludgeons, if that cannot be avoided, one relevant fact is
that the same representation convention is used for Windows "atoms", but
atoms are dynamically allocated things, whereas kludgeons are not.

The language identification is constrained by the set of languages
supported by Windows, i.e., generalizing it can be problematic.

The file specification can be (3a) some identification of a file system
file, e.g. a path (there are also other ways to identify a file, but
probably irrelevant), or (3b) a 32-bit module identifier, called a
"module handle", where a /module/ is the loaded image of an executable
or DLL, such as the loaded image of the currently executing program.

Ordinarily one wants the file to default to the currently executing
program (a module handle is very easily obtained from the API level),
and the language specification to default to the empty specification.
</what to design a C++ solution for>

The main requirements are (1) correctness and safety, (2) clarity, and
(3) efficiency, since this is for my third installment about Windows
programming (for the two first installments, see <url:
http://groups.google.c om/group/comp.os.ms-windows.program mer.win32/browse_thread/thread/fc61acc7316d925 7/892100ca99fe820 0>
or, as tinyurl, <url: http://tinyurl.com/pgzlq>). Functionality,
especially general file specification functionality, can suffer.

It's no big deal to design a "working" solution; in fact, the API level
itself is a "working" solution, so for that, nothing more is needed.

What I'm up against is a conflict between the three main requirements;
it's difficult to satisfy all three.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Apr 30 '06 #1
9 2855
"Alf P. Steinbach" <al***@start.no > wrote in message
news:4b******** *****@individua l.net...
It's no big deal to design a "working" solution; in fact, the API level
itself is a "working" solution, so for that, nothing more is needed.


If the API consists of kludgeons put together by a couple of kludgers would
that make us poor users 'kludgees'?

[jw]
May 1 '06 #2
Could someone translate that to English?

But seriously, as far as I understand you're interested in a solution for including data into executable that would be: 1)correct and safe, 2)clare and 3)efficient.
And for some obvious reasons using default windows resources and loading them using a bunch of deprecated functions like the code below (no error checking):

HRSRC hres;
HGLOBAL hglob;
void* p;

hres = FindResource(Ge tModuleHandle(N ULL),id,type);
hglob = LoadResource(Ge tModuleHandle(N ULL),hres);
p = LockResource(hg lob);
FreeResource(hR es);

does not meet at least one of the three established conditions (and perhaps does not meet any). I assume here simplified version of the problem when resources are within executable itself and there is only one language version of the resource.

I believe resources are commonly used because it's easy to both create and include them, though loading is not very elegant. Also the example above refers to the custom types resources, using some predefined types is often easier.

As to more general C++ approach, the best (fully portable and easy to access from within a code) way of including data is simply to incude the data into the code as table or some custom struct in a dedicated header/header+code file(s). The disadvantage here is that the first step (creating and including) requires more effort, because any data needs to be converted to C++ readable format.

This approach fulfils 1) and also 3) if by efficiency is meant executing the code (if creating then not necessary).
I would say it fulfils 2) as well but clarity is a subjective thing.

--
677265676F72794 0346E6575726F6E 732E636F6D
May 1 '06 #3
Grzegorz Wróbel </dev/nu**@localhost. localdomain> wrote:
HRSRC hres;
HGLOBAL hglob;
void* p;
hres = FindResource(Ge tModuleHandle(N ULL),id,type);
hglob = LoadResource(Ge tModuleHandle(N ULL),hres);
p = LockResource(hg lob);
FreeResource(h Res);


You're not meant to use FreeResource. It does nothing. So just

HRSRC hres = FindResource(hI nstance,id,type );
hglob = LoadResource(hI nstance,hres);
void *p = LockResource(hg lob)

and no need to free anything. I actually find these three lines rather
beautiful, clean, understandable and easy! Alf, in your quest to make
a framework/wrapper, I think that these three should be at the BOTTOM
of your priority list.

--
Lucian
May 1 '06 #4
Lucian Wischik wrote:
Grzegorz Wróbel </dev/nu**@localhost. localdomain> wrote:
HRSRC hres;
HGLOBAL hglob;
void* p;
hres = FindResource(Ge tModuleHandle(N ULL),id,type);
hglob = LoadResource(Ge tModuleHandle(N ULL),hres);
p = LockResource(hg lob);
FreeResource( hRes);

You're not meant to use FreeResource. It does nothing. So just

HRSRC hres = FindResource(hI nstance,id,type );
hglob = LoadResource(hI nstance,hres);
void *p = LockResource(hg lob)

and no need to free anything. I actually find these three lines rather
beautiful, clean, understandable and easy! Alf, in your quest to make
a framework/wrapper, I think that these three should be at the BOTTOM
of your priority list.


You right FreeResource() is obsolete and along with UnlockResource( ) left only for backward compatibility reasons. I just copied and paste some code from one of my old projects.

And what I meant by deprecated was that LoadResource() return HGLOBAL type although handle it returns is not really a pointer to a global memory block. This is also for backward compatibility with Win16 code.
So what beatiful you see in this remnant of ancient times? I quess you are a romantic soul.

I personally dislike this weirdness when you need LoadSomething() which returns HGLOBAL type and then LockSomething() , which still resides in some parts of win32 (and win64 now) code for backward compatibility with 16bit code. Examples are some resources functions and clibboard access functions. But of course I still use it :) I take Alf's question as more theoretical than practical.

--
677265676F72794 0346E6575726F6E 732E636F6D
May 1 '06 #5
Grzegorz Wróbel </dev/nu**@localhost. localdomain> wrote:
So what beatiful you see in this remnant of ancient times? I quess you are a romantic soul.


Sure, the return types are weird and wrong as you say. And the
FindResource/LoadResource could reasonably be rolled into a single
call. What I like about it is that it's three lines, you don't need to
free it, and it's small+compact to look at, and you know exactly what
it's doing (i.e. no hidden background machinery)

--
Lucian
May 1 '06 #6
* Lucian Wischik:
Grzegorz Wróbel </dev/nu**@localhost. localdomain> wrote:
HRSRC hres;
HGLOBAL hglob;
void* p;
hres = FindResource(Ge tModuleHandle(N ULL),id,type);
hglob = LoadResource(Ge tModuleHandle(N ULL),hres);
p = LockResource(hg lob);
FreeResource(hR es);


You're not meant to use FreeResource. It does nothing. So just

HRSRC hres = FindResource(hI nstance,id,type );
hglob = LoadResource(hI nstance,hres);
void *p = LockResource(hg lob)

and no need to free anything. I actually find these three lines rather
beautiful, clean, understandable and easy! Alf, in your quest to make
a framework/wrapper, I think that these three should be at the BOTTOM
of your priority list.


Perhaps. But add error checking and MAKEINTRESOURCE calls (converting
integers to kludgeon pointers). However, wrapping these three calls in a
single function is not a big deal; the problem lies not with
encapsulating the three calls above in a single function, i.e. not with
the procedural aspect, but with representing id+type as a cohesive unit
that can be safely passed around and that centralizes the
MAKEINTRESOURCE calls, perhaps also dealing with type safety of
resources, while not needlessly sacrificing efficiency.

At the lowest level, tackling just the kludgeon representation, I'm
thinking something like

// The intent of this class is to provide safety & clarity
// (especially wrt. string lifetime), while preserving efficiency
// for integer atom-like names.
class AtomLikeName
{
private:
std::wstring myIdentifier;
unsigned short myIntValue;

public:
AtomLikeName( std::wstring const& value )
: myIdentifier( value )
, myIntValue( 0 )
{
assert( myIdentifier.le ngth() > 0 );
}

AtomLikeName( unsigned short value, bool isAtom = false )
: myIntValue( value )
{
assert( 0 < myIntValue );
assert( myIntValue <= (isAtom? 0xBFFF : 0x7FFF) );
}

bool isPseudoPointer () const { return (myIntValue != 0); }

// Can be a pseudo-pointer:
wchar_t const* value() const
{
return (isPseudoPointe r()?
MAKEINTRESOURCE ( myIntValue ) : myIdentifier.c_ str()
);
}

// Comparision operations can be defined in terms of asString().
std::wstring asString() const
{
return (isPseudoPointe r()?
L"#" + stringFrom( myIntValue ) : myIdentifier
);
}
};

Then an id+type+(possib le language)+(more remotely possible file spec)
can be added on top.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
May 1 '06 #7
Lucian Wischik wrote:
Sure, the return types are weird and wrong as you say. And the
FindResource/LoadResource could reasonably be rolled into a single
call. What I like about it is that it's three lines, you don't need to
free it, and it's small+compact to look at, and you know exactly what
it's doing (i.e. no hidden background machinery)


True..

But I would add at least one check at the end to see if resource has been correctly loaded. This would render 5 lines and 3 variables. Not that bad as many windows specific stuff requires much more.
Now compare this to the pure C++ alternative I described: 0 lines and 1 variable declared/defined in header file, ready to use.
I don't count here dedicated header/code files as real code since they are practicaly generated and I treat them as equivalent of .rc and "resource.h " files. Of course the cost for that is additional work with generating those from files that normaly would be included as a resource. So running external progam and perhaps some copy/paste "labour".
Also it is worth to mention that resources are easily crackable by PE-format editors unless file has been compressed using a custom compressing routine. So in case it does matter different approach is worth considerating.

I quess most find resources more comfortable to use, especially if their IDE provides build in resource editor/wizard and that they are already familiar with resources since those are used for dialog templates, icons, etc., but it's good to be aware there are alternatives.
But now back to the OP's problem. As I gather it Alf is witing some paper - a tutorial for windows programming and wants to provide a chapter about way of including external data into the program.
So, is the resource approach
1) correct and safe?
Loading resource may fail, though in case it's included in the very same executable that loads it, it's very unlikely unless resource section has been corrupted or edited by some PE format editor.
2) clear?
From my experience, when I had to use it for the first time - no. I was confused by this return types. I was really suprised Microsoft didn't provide additionally, valid non-backward compatible method(s) except this backward compatible weirdiness.
3)efficient?
Since you generally load resource only once (at least custom one) it doesn't matter that much.

If Alf's concern is only about identifiers then with pure C++ approach he can decide and define the way "resources" are identified by himself.

--
677265676F72794 0346E6575726F6E 732E636F6D
May 1 '06 #8
On Mon, 01 May 2006 20:51:35 +0200, "Alf P. Steinbach"
<al***@start.no > wrote:
* Lucian Wischik:
Grzegorz Wróbel </dev/nu**@localhost. localdomain> wrote:
HRSRC hres;
HGLOBAL hglob;
void* p;
hres = FindResource(Ge tModuleHandle(N ULL),id,type);
hglob = LoadResource(Ge tModuleHandle(N ULL),hres);
p = LockResource(hg lob);
FreeResource(hR es);


You're not meant to use FreeResource. It does nothing. So just

HRSRC hres = FindResource(hI nstance,id,type );
hglob = LoadResource(hI nstance,hres);
void *p = LockResource(hg lob)

and no need to free anything. I actually find these three lines rather
beautiful, clean, understandable and easy! Alf, in your quest to make
a framework/wrapper, I think that these three should be at the BOTTOM
of your priority list.


Perhaps. But add error checking and MAKEINTRESOURCE calls (converting
integers to kludgeon pointers). However, wrapping these three calls in a
single function is not a big deal; the problem lies not with
encapsulatin g the three calls above in a single function, i.e. not with
the procedural aspect, but with representing id+type as a cohesive unit
that can be safely passed around and that centralizes the
MAKEINTRESOURC E calls, perhaps also dealing with type safety of
resources, while not needlessly sacrificing efficiency.

At the lowest level, tackling just the kludgeon representation, I'm
thinking something like

// The intent of this class is to provide safety & clarity
// (especially wrt. string lifetime), while preserving efficiency
// for integer atom-like names.
class AtomLikeName
{
private:
std::wstring myIdentifier;
unsigned short myIntValue;

public:
AtomLikeName( std::wstring const& value )
: myIdentifier( value )
, myIntValue( 0 )
{
assert( myIdentifier.le ngth() > 0 );
}

AtomLikeName( unsigned short value, bool isAtom = false )
: myIntValue( value )
{
assert( 0 < myIntValue );
assert( myIntValue <= (isAtom? 0xBFFF : 0x7FFF) );
}

bool isPseudoPointer () const { return (myIntValue != 0); }

// Can be a pseudo-pointer:
wchar_t const* value() const
{
return (isPseudoPointe r()?
MAKEINTRESOURCE ( myIntValue ) : myIdentifier.c_ str()
);
}

// Comparision operations can be defined in terms of asString().
std::wstring asString() const
{
return (isPseudoPointe r()?
L"#" + stringFrom( myIntValue ) : myIdentifier
);
}
};

Then an id+type+(possib le language)+(more remotely possible file spec)
can be added on top.


Don't forget that resources in Windows can be created on the fly. They
don't have to be embedded in the executable or a DLL, although that is
a popular alternative.

Just an idea I have been playing with:
One could have a factory class for each kind of resource and let the
factory be a template taking a parameter of different kinds of
resource managers. In the debugging phase, for example, resource data
could be kept in a configuration file (e.g. XML, or even an INI file)
which would be read by the resource manager as text. The binary
resource would be created on the fly by the resource manager. Slow, of
course, but a whole lot easier to edit during development. No
recompiling, no linking, just edit the configuration and run.

Once everything is satisfactory, the configuration file could be
parsed and compiled as a RES file by an external tool and linked to
the executable. The template resource manager used for debugging would
be swapped for one that loads resources the "normal" way.

I believe this is similar to how some GUI libraries manage resources
on Linux, isn't it?

--
Bob Hairgrove
No**********@Ho me.com
May 1 '06 #9
[Bob, I think the discussion you aim for is off-topic in clc++ since it
doesn't involve C++, so I'm setting follow-ups; please honor.]

* Bob Hairgrove:

Don't forget that resources in Windows can be created on the fly.
Depends what you mean: obviously they can be created, and hence, on the fly.

They
don't have to be embedded in the executable or a DLL, although that is
a popular alternative.
Classic API-level resources have to be embedded in files, mainly because
they're used without regard for deallocation.

Just an idea I have been playing with:
One could have a factory class for each kind of resource and let the
factory be a template taking a parameter of different kinds of
resource managers. In the debugging phase, for example, resource data
could be kept in a configuration file (e.g. XML, or even an INI file)
which would be read by the resource manager as text. The binary
resource would be created on the fly by the resource manager. Slow, of
course, but a whole lot easier to edit during development. No
recompiling, no linking, just edit the configuration and run.
XML resources like you describe are supported by many environments,
including Java and Windows .NET.

It's not a case of edit-and-go, however.

On the contrary, for all but the most trivial kinds of resources it
typically involves a lot of obscure under-documented or undocumented
tools and API's, e.g. conversion to and back from Base-64. It's IMHO an
over-generalization that only barely delivers the basic functionality,
and then in an inefficient and needlessly complex way. Unfortunately,
those who make the decisions about what we should use in the future, by
backing this or that approach so that support becomes available, have a
vested interest in selling tools, seminars and so on, and are perhaps
not so much engineers as buzz-word compliant managers with $$$ eyes.

Once everything is satisfactory, the configuration file could be
parsed and compiled as a RES file by an external tool and linked to
the executable. The template resource manager used for debugging would
be swapped for one that loads resources the "normal" way.
Uh. Microsoft is introducing something like that in Windows Vista.
It's ugly, and it's over-generalized. It tries to fix that which
doesn't need fixing, and solve that which is already solved, instead of
fixing the things that are broken (such as the documentation.. .).

I believe this is similar to how some GUI libraries manage resources
on Linux, isn't it?


Everywhere, unfortunately.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
May 1 '06 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

43
4873
by: grz02 | last post by:
Hi, Im an experienced database+software designer and developer, but, unfortunately, anything to do with web-programming and web-systems designs is still a pretty new area to me... (been working mostly with "legacy" environments the last 10 years) So I am writing this, hoping to get some useful advise and feedback... I have done some pretty trivial, small websites with html/PHP,
11
3187
by: Arsen Vladimirskiy | last post by:
Hello, If I have a few simple classes to represent Entities such as Customers and Orders. What is the proper way to pass information to the Data Access Layer? 1) Pass the actual ENTITY to the Data Access Layer method -or- 2) Pass some kind of a unique id to the Data Access Layer method
10
2139
by: Saso Zagoranski | last post by:
hi, this is not actually a C# problem but since this is the only newsgroup I follow I decided to post my question here (please tell me where to post this next time if you think this post shouldn't be here). I have two design questions: 1. what is the correct (or best) way to include database queries into the code if you plan on
3
1871
by: reageer | last post by:
Hi all, I have a design question: I have a bunch of users (name, address, zip, etc.). They are assigned a card with a specific id. The only thing unique is this card id, or probably the combination of all other user fields. So it's seductive to use the card id as the primary key. This card allows access to certain places and all access is logged.
11
2364
by: John Fly | last post by:
I'm working on a large project(from scratch). The program is essentially a data file processor, the overall view is this: A data file is read in, validated and stored in a memory structure similar to a database or XML representation. Rules to modify the stored data will be executed, then the data will be transformed into an output format. Think something similar to FormatA -> XML -> Manipulate XML -> FormatB
44
2820
by: Mikito Harakiri | last post by:
This is a continuation of the old theme, now featuring xml. <tree> <node id=0 parent_id=null label='A'> <node id=1 parent_id=0 label='B'> <node id=2 parent_id=0 label='C'> ... </tree>
0
1436
by: heidan | last post by:
Dear, I have a question of representing the relationship of sales invoice's posting date and post period into RDF. Let's say every sales invoice has a posting date which records when this invoice is created; posting period has a 'from posting date' and 'to posting date'; Every sales invoice must be posted into one posint period, that implies following conditions.
6
3376
by: Stephen Torri | last post by:
I am trying to produce a singleton class that I can use throughout my library to write tracing information to a file. My intent was to design such that someone using the library in its debug mode would be able to see what was happening without having to use a debugger to step through each instruction. What they would do is run their program and view the tracing file output. If there was something wrong then they would use the debugger of...
2
9842
by: existential.philosophy | last post by:
This is a new problem for me: I have some queries that open very slowly in design view. My benchmark query takes about 20 minutes to open in design view. That same query takes about 20 minutes to open in datasheet view. As an experiment, I deleted all rows in all tables; after that, the query took only seconds to open in both design view and datasheet view. From these facts, I conclude that Access is evaluating the query when I go to...
0
9645
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
10327
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10151
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
10092
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9950
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
8973
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
7499
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6740
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
2
3647
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.