470,849 Members | 925 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 470,849 developers. It's quick & easy.

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 1977
[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 discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

19 posts views Thread by Deniz Bahar | last post: by
4 posts views Thread by ±čµż±Ő | last post: by
44 posts views Thread by bahadir.balban | last post: by
reply views Thread by Evelyne | last post: by
15 posts views Thread by xargon | last post: by
12 posts views Thread by Letsee++ | last post: by
3 posts views Thread by mrbrightsidestolemymoney | last post: by
24 posts views Thread by Aaron Gray | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.