473,403 Members | 2,183 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,403 software developers and data experts.

Overloaded vendor library routine: is this C++? Or very clever C?

I've inherited some code which uses an undocumented feature of a
third-party vendor's library. Essentially, this vendor has kept the
details of an interface struct secret, but we can pass a pointer to
this struct to other vendor routines. The struct describes a complex
time-varying object, but it basically boils down to an integer, and
there are access routines to get to the current value of this integer.

My problem is:

1) Our code is C, and the vendor's library is, I think, also C

2) This undocumented feature allowed my (ex) colleague's code to read
the integer directly from the pointer. In other words, the return
value is somehow overloaded.

How is this possible? My only thought is that the vendor library is
actually C++, but even if it is, I still can't see how to make this
work.

Here's a test program that shows this (it compiles Ok as a stand-alone
routine):

#include <stdio.h>

typedef struct dummyTag * dummy; // secret vendor struct

extern dummy bar(void); // vendor's access routine

void foo(void) {
int wibble;
wibble = (long)bar(); // shouldn't be possible, but...
printf("wibble is %d\n", wibble); // works!!
}

Is this possible in C? Or does the vendor library have to be C++? If
it is C++, how does this work? I'm compiling with gcc and I can't see
how this module could interface with a C++ class with overloaded
access routines.

Many thanks -

Jack

May 14 '06 #1
12 2176
[Followups set to comp.lang.c]

Jack Daly said:
I've inherited some code which uses an undocumented feature of a
third-party vendor's library. Essentially, this vendor has kept the
details of an interface struct secret, but we can pass a pointer to
this struct to other vendor routines. The struct describes a complex
time-varying object, but it basically boils down to an integer, and
there are access routines to get to the current value of this integer.
In short, you have an opaque type. So far so good.
My problem is:

1) Our code is C, and the vendor's library is, I think, also C
That's not a problem. That's an opportunity. :-)
2) This undocumented feature allowed my (ex) colleague's code to read
the integer directly from the pointer. In other words, the return
value is somehow overloaded.
Well, perhaps there is a simpler explanation.

How is this possible? My only thought is that the vendor library is
actually C++, but even if it is, I still can't see how to make this
work.

Here's a test program that shows this (it compiles Ok as a stand-alone
routine):

#include <stdio.h>

typedef struct dummyTag * dummy; // secret vendor struct

extern dummy bar(void); // vendor's access routine

void foo(void) {
int wibble;
wibble = (long)bar(); // shouldn't be possible, but...
printf("wibble is %d\n", wibble); // works!!
Well, what you've done is converted a pointer into an integer, which is
legal if you cast it. The resulting information is normally pretty
meaningless, but you seem to think there is meaning in the value you get.
What makes you think that?

If that really is the value that the secret struct stores, then presumably
it's written something like this:

dummy bar(void)
{
return (dummy)secretnumber;
}
}

Is this possible in C?


I don't think you've yet established that overloading is occurring.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
May 14 '06 #2
Jack Daly wrote:

I've inherited some code which uses an undocumented feature of a
third-party vendor's library. Essentially, this vendor has kept the
details of an interface struct secret, but we can pass a pointer to
this struct to other vendor routines. The struct describes a complex
time-varying object, but it basically boils down to an integer, and
there are access routines to get to the current value of this integer. 2) This undocumented feature allowed my (ex) colleague's code to read
the integer directly from the pointer. In other words, the return
value is somehow overloaded.

How is this possible?


If I had a struct
where I could read an integer directly from a pointer to the struct,
it would mean something different from what you described,
which I snipped.

If you convert the address of a struct
to a pointer to the type of it's first member,
then that result will be a pointer to the first member of the struct.
If that first member were an integer,
then that's what I would mean by being able to access
an integer directly from a pointer to the struct.

I'm reading this crosspost from clc.

--
pete
May 14 '06 #3
On Sun, 14 May 2006 12:47:05 GMT, pete <pf*****@mindspring.com> wrote:
If you convert the address of a struct
to a pointer to the type of it's first member,
then that result will be a pointer to the first member of the struct.
If that first member were an integer,
then that's what I would mean by being able to access
an integer directly from a pointer to the struct.
Hmmm.. but the code casts to a long, rather than a long*:
void foo(void) {
int wibble;
wibble = (long)bar(); // shouldn't be possible, but...
printf("wibble is %d\n", wibble); // works!!
}


If this was C, then the printf should be printing an address, but it
actually prints (from memory, for 4 calls) 2, 18, 0, 0, which is
exactly what I'd expect for these 4 VHDL signals, which are two
integers with values 2 and 18, and two booleans with value false.

So, I don't think it can be C, even buggy C. On the other hand, I
don't see how it can be C++, for 2 reasons:

1 - this compilation unit includes nothing which describes the
internals of 'struct dummyTag'. I didn't think this was possible in
C++ - doesn't the compiler need to know, when compiling this file,
that 'struct dummyTag' is a class which can be read to return a long?

2 - I can't see how I can compile with gcc, rather than g++.

Thanks -

Jack
May 14 '06 #4
Jack Daly wrote:
If this was C, then the printf should be printing an address, but it
actually prints (from memory, for 4 calls) 2, 18, 0, 0, which is
exactly what I'd expect for these 4 VHDL signals, which are two
integers with values 2 and 18, and two booleans with value false.

So, I don't think it can be C, even buggy C. On the other hand, I
don't see how it can be C++, for 2 reasons:

1 - this compilation unit includes nothing which describes the
internals of 'struct dummyTag'. I didn't think this was possible in
C++ - doesn't the compiler need to know, when compiling this file,
that 'struct dummyTag' is a class which can be read to return a long?

2 - I can't see how I can compile with gcc, rather than g++.

Thanks -

Jack


I think Richard Heathfield's post (up the thread) is plausible: in bar,
the vendor is c-casting a long to a dummyTag *, which he then passes
back to you.

The vendor is very clearly saying "keep your mitts off of this thing".
You're ex-colleague is very clearly saying "get stuffed, vendor" :o
May 14 '06 #5
Jack Daly <jd****@yahoo.com> writes:
I've inherited some code which uses an undocumented feature of a
third-party vendor's library. Essentially, this vendor has kept the
details of an interface struct secret, but we can pass a pointer to
this struct to other vendor routines. The struct describes a complex
time-varying object, but it basically boils down to an integer, and
there are access routines to get to the current value of this integer.

My problem is:

1) Our code is C, and the vendor's library is, I think, also C

2) This undocumented feature allowed my (ex) colleague's code to read
the integer directly from the pointer. In other words, the return
value is somehow overloaded.

How is this possible? My only thought is that the vendor library is
actually C++, but even if it is, I still can't see how to make this
work.

Here's a test program that shows this (it compiles Ok as a stand-alone
routine):

#include <stdio.h>

typedef struct dummyTag * dummy; // secret vendor struct

extern dummy bar(void); // vendor's access routine

void foo(void) {
int wibble;
wibble = (long)bar(); // shouldn't be possible, but...
printf("wibble is %d\n", wibble); // works!!
}

Is this possible in C? Or does the vendor library have to be C++? If
it is C++, how does this work? I'm compiling with gcc and I can't see
how this module could interface with a C++ class with overloaded
access routines.


[Followups redirected to comp.lang.c.]

You're assuming that the code might be C++ because you think it's
doing "overloading". You've misunderstood the meaning of the term.

Overloading means using the same name for two different functions or
operators. In C++, you can have two different functions both named
"foo", as long as they take different types of arguments. When the
compiler sees a call to foo(), it determines which function to call by
looking at the arguments. Likewise, you can overload operators as
functions; the C++ standard library does this to use the shift
operators "<<" and ">>" for I/O. When the compiler sees
(cout << "hello"), it decides what to do based on the types of the
operands.

None of this is supported in C, and none of this has anything to do
with the code you posted.

The code you posted is simply converting an expression of one type
(dummy, a pointer type) to another type (long). This is perfectly
legal in C (and in C++), but the result won't necessarily be
meaningful.

Another suspicious thing in the code you posted is that the result of
bar() is converted to long, and then assigned to an int. There may or
may not be a good reason to do that.

The function bar() returns a pointer. Possibly the pointer it returns
is obtained by converting an integer value to the pointer type. The
caller then converts from a pointer type back to an integer type.
This is a dangerously non-portable thing to do -- but sometimes
dangerously non-portable code is what's needed to do the job.

It's also possible that the value returned by bar() is a valid pointer
value, to be used only by the vendor's code, and your function foo()
is abusing it by converting it to long and getting a meaningless
result. (If you're determined to do something dangerous, C won't
necessarily stop you.)

If you just want to display the value returned by bar(), you can use
printf's "%p" format:

void foo(void)
{
dummy wibble = bar();
printf("wibble is %p\n", (void*)wibble);
}

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
May 14 '06 #6
On Sun, 14 May 2006 15:24:37 GMT, Howard Gardner <hg******@rawbw.com>
wrote:
Jack Daly wrote: I think Richard Heathfield's post (up the thread) is plausible: in bar,
the vendor is c-casting a long to a dummyTag *, which he then passes
back to you.


Yes, I'm afraid that I missed that. This would be plausible, except
that dummyTag* has real functionality. I can pass a dummyTag* back to
the library to get it to do clever things with the signal. This would
be impossible if it was simply an integer giving the current value of
the signal; it must actually be an object describing a signal.

So, it seems to me that the library is actually C++, and 'bar' has a
copy assignment operator which returns a long. However, the compiler
can't and doesn't know this, so presumably all the magic (or the
error) is in the gnu linker. I wouldn't have expected this to be
possible.

Jack
May 15 '06 #7
On Sun, 14 May 2006 18:36:35 GMT, Keith Thompson <ks***@mib.org>
wrote:
Jack Daly <jd****@yahoo.com> writes:
wibble = (long)bar(); // shouldn't be possible, but...
printf("wibble is %d\n", wibble); // works!!
}

Is this possible in C? Or does the vendor library have to be C++? If
it is C++, how does this work? I'm compiling with gcc and I can't see
how this module could interface with a C++ class with overloaded
access routines.
You're assuming that the code might be C++ because you think it's
doing "overloading". You've misunderstood the meaning of the term.
Ok, to be more specific: I'm postulating that the vendor has supplied
a C++ library which has (at least) two copy assignment operators:

long operator=(const bar& rhs) {...}
bar* operator=(const bar& rhs) {...}

Somehow, this C code has linked with the C++ library and the
assignment 'wibble = (long)bar()' is using the first operator.
The code you posted is simply converting an expression of one type
(dummy, a pointer type) to another type (long). This is perfectly
legal in C (and in C++), but the result won't necessarily be
meaningful.
But it *is* meaningful... that's the whole problem. The interesting
thing is - *why* is it meaningful?
The function bar() returns a pointer. Possibly the pointer it returns
is obtained by converting an integer value to the pointer type. The
caller then converts from a pointer type back to an integer type.
This is a dangerously non-portable thing to do -- but sometimes
dangerously non-portable code is what's needed to do the job.
See my reply to Howard - I don't think this is possible. The value
returned by the vendor's 'bar' is, in normal circumstances, meant to
be a real object pointer describing a complex signal - you can pass it
back to the vendor's library, and do complicated things with it.
That's how the vendor's docs describe it, and that's how everybody
else uses the library, including my departed colleague, except in
these 4 cases that I'm trying to figure out. I'd ignore it except that
I think there's something to be learnt here.
It's also possible that the value returned by bar() is a valid pointer
value, to be used only by the vendor's code, and your function foo()
is abusing it by converting it to long and getting a meaningless
result.


No, it's getting a real and valid result - see my two previous
replies. There's no chance that the pointer could display as the
expected current value of the signal (the 4 values it's displaying are
2, 18, 0, and 0, which are exactly correct).

Jack
May 15 '06 #8
Jack Daly wrote:
On Sun, 14 May 2006 18:36:35 GMT, Keith Thompson <ks***@mib.org>
wrote:

Jack Daly <jd****@yahoo.com> writes:
wibble = (long)bar(); // shouldn't be possible, but...
printf("wibble is %d\n", wibble); // works!!
}

Is this possible in C? Or does the vendor library have to be C++? If
it is C++, how does this work? I'm compiling with gcc and I can't see
how this module could interface with a C++ class with overloaded
access routines.
You're assuming that the code might be C++ because you think it's
doing "overloading". You've misunderstood the meaning of the term.

Ok, to be more specific: I'm postulating that the vendor has supplied
a C++ library which has (at least) two copy assignment operators:

long operator=(const bar& rhs) {...}
bar* operator=(const bar& rhs) {...}


That isn't possible in C++ - you can't overload assignment for built in
types. Nor can you overload the type conversion operator for pointers.
Somehow, this C code has linked with the C++ library and the
assignment 'wibble = (long)bar()' is using the first operator.
I'm afraid this isn't possible - C++ doesn't do what you are talking
about anyway, and in any case it would require the compiler, not linker.
The code you posted is simply converting an expression of one type
(dummy, a pointer type) to another type (long). This is perfectly
legal in C (and in C++), but the result won't necessarily be
meaningful.

But it *is* meaningful... that's the whole problem. The interesting
thing is - *why* is it meaningful?


Could the number returned not be an index or key into a table? This is
how, for example, Microsoft's opaque HANDLE pointers work.
The function bar() returns a pointer. Possibly the pointer it returns
is obtained by converting an integer value to the pointer type. The
caller then converts from a pointer type back to an integer type.
This is a dangerously non-portable thing to do -- but sometimes
dangerously non-portable code is what's needed to do the job.

See my reply to Howard - I don't think this is possible. The value
returned by the vendor's 'bar' is, in normal circumstances, meant to
be a real object pointer describing a complex signal - you can pass it
back to the vendor's library, and do complicated things with it.


It need not be a valid pointer for that. What happens if you print out
the pointer value, e.g.
printf("wibble is %p\n", (void*)wibble);
No, it's getting a real and valid result - see my two previous
replies. There's no chance that the pointer could display as the
expected current value of the signal (the 4 values it's displaying are
2, 18, 0, and 0, which are exactly correct).


What do those values represent?

Tom
May 15 '06 #9
Jack Daly <jd****@yahoo.com> writes:
On Sun, 14 May 2006 18:36:35 GMT, Keith Thompson <ks***@mib.org>
wrote:
Jack Daly <jd****@yahoo.com> writes:
wibble = (long)bar(); // shouldn't be possible, but...
printf("wibble is %d\n", wibble); // works!!
}

Is this possible in C? Or does the vendor library have to be C++? If
it is C++, how does this work? I'm compiling with gcc and I can't see
how this module could interface with a C++ class with overloaded
access routines.

You're assuming that the code might be C++ because you think it's
doing "overloading". You've misunderstood the meaning of the term.


Ok, to be more specific: I'm postulating that the vendor has supplied
a C++ library which has (at least) two copy assignment operators:

long operator=(const bar& rhs) {...}
bar* operator=(const bar& rhs) {...}

Somehow, this C code has linked with the C++ library and the
assignment 'wibble = (long)bar()' is using the first operator.


There's no need to assume C++ to explain the behavior you're seeing.
C code is perfectly capable of subverting the type system.

Here's a simple C program in which a function returning a pointer can
return either an actual pointer, or an integer converted to a pointer;
the caller knows what to expect based on the argument it passed to it.

#include <stdio.h>
#include <stdlib.h>

void *func(int n)
{
if (n == 0) {
return malloc(100);
}
else {
return (void*)n;
}
}

int main(void)
{
printf("func(0) returns %p\n", func(0));
printf("func(1) returns %d\n", (int)func(1));
return 0;
}

This is ugly, non-portable code that can easily fail if int and void*
are of different sizes -- or even if they're the same size. But it
may be similar to what your library is doing.

Have you tried asking the vendor?

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
May 15 '06 #10
Jack Daly wrote:

On Sun, 14 May 2006 15:24:37 GMT, Howard Gardner <hg******@rawbw.com>
wrote:
Jack Daly wrote:

I think Richard Heathfield's post (up the thread) is plausible:
in bar,
the vendor is c-casting a long to a dummyTag *, which he then passes
back to you.


Yes, I'm afraid that I missed that. This would be plausible, except
that dummyTag* has real functionality. I can pass a dummyTag* back to
the library to get it to do clever things with the signal. This would
be impossible if it was simply an integer giving the current value of
the signal; it must actually be an object describing a signal.

So, it seems to me that the library is actually C++, and 'bar' has a
copy assignment operator which returns a long. However, the compiler
can't and doesn't know this, so presumably all the magic (or the
error) is in the gnu linker. I wouldn't have expected this to be
possible.


The conversion of a pointer type to an integer type
is implementation defined.
What does your implementaion's documentation say?

--
pete
May 15 '06 #11

Keith Thompson wrote:
[Followups redirected to comp.lang.c.]
Fixed...
You're assuming that the code might be C++ because you think it's
doing "overloading". You've misunderstood the meaning of the term.

Overloading means using the same name for two different functions or
operators. In C++, you can have two different functions both named
"foo", as long as they take different types of arguments. When the
compiler sees a call to foo(), it determines which function to call by
looking at the arguments. Likewise, you can overload operators as
functions; the C++ standard library does this to use the shift
operators "<<" and ">>" for I/O. When the compiler sees
(cout << "hello"), it decides what to do based on the types of the
operands.

None of this is supported in C, and none of this has anything to do
with the code you posted.

The code you posted is simply converting an expression of one type
(dummy, a pointer type) to another type (long). This is perfectly
legal in C (and in C++), but the result won't necessarily be
meaningful.


You can overload a "cast" operator in C++. This must be what he thinks
is happening. However, it won't work with the construct the OP is
saying is being worked with. You can't overload the casting of a
primitive type - any kind of real pointer qualifies as such (you can
have things that /look/ like pointers that could be overridden but not
a pointer like in the OP's post).

Example:

struct X
{
public:

operator long () { return 5; }
};

X x;

long y = x;

But this still won't work:

X *x = new X;

long y = (long)x;

Still have ptr value of x.

What the OP thinks is happening is not possible in either language.

May 15 '06 #12
But this still won't work:

X *x = new X;

long y = (long)x;

Still have ptr value of x.

What the OP thinks is happening is not possible in either language.

I haven't read the rest of the thread, so I don't know what's being
discussed.
X &x = *new X;

long y = x;
-Tomás
May 15 '06 #13

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

Similar topics

19
by: Deniz Bahar | last post by:
Hi, I would like to call one of my functions the exact name as an existing C library function (for example K&R2 exercises asks me to make an atof function). If I don't include the header with...
4
by: ±čµż±Ő | last post by:
Tell me why the symbol "_" use in the Library? For example, char *_itoa( int value, char *string, int radix ); But We use function "itoa(value,string,radix) "only. I want to know the...
44
by: bahadir.balban | last post by:
Hi, What's the best way to implement an overloaded function in C? For instance if you want to have generic print function for various structures, my implementation would be with a case...
0
by: Evelyne | last post by:
1. my vendor interface is defined in an h & c file: _EXTERN S16BIT _DECL aceSetIrqConditions(S16BIT DevNum, U16BIT bEnable, U32BIT dwIrqMask,void(_DECL *funcExternalIsr)(S16BIT DevNum, U32BIT...
15
by: xargon | last post by:
Hi everyone, I am writing a small user interface library in C++ (I know it has been done to death, but it is good for learning ). Anyways, I need some help/advice with the deisgn of the...
12
by: Letsee++ | last post by:
hi, is it possible to write a program to read and print a number without using standard library functions in C and C++? if yes ....how? waiting for a reply...
14
by: Jack Daly | last post by:
I've inherited some code which uses an undocumented feature of a third-party vendor's library. Essentially, this vendor has kept the details of an interface struct secret, but we can pass a pointer...
3
by: mrbrightsidestolemymoney | last post by:
Hi, I need to write out a 1d array of 2d arrays (the structures for each are custom, a 3d structure is defined but not suitable for my use for a number of reasons). Templated routines exist...
24
by: Aaron Gray | last post by:
From what I have been looking at for Javascript library development, browsers that support Javascript 1.5/ECMAScript 3/JScript 5.5 looks like the base level to pitch at. Anyone add anything ? ...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
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,...
0
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,...
0
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...
0
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...
0
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,...
0
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...

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.