tags:

views:

451

answers:

2

I am writing a DLL with mixed C/C++ code. I want to specify the ordinals of the functions I'm exporting. So I created a .DEF file that looks like this

LIBRARY LEONMATH

EXPORTS

    sca_alloc   @1
    vec_alloc   @2
    mat_alloc   @3

    sca_free    @4
    vec_free    @5
    mat_free    @6

    ...

I would like to specify the ordinals of my C++ functions and class methods too. I have tried using the Dependency Walker to add the mangled names of my functions to the .DEF file:

    ??0CScalar@@QAE@XZ      @25
    ??0CScalar@@QAE@O@Z     @26
    ??0CScalar@@QAE@ABV0@@Z @27
    ??1CScalar@@QAE@XZ      @28

But this has failed. Any ideas why this could be happening?


EDIT: kauppi made a good observation, so I'm adding more information to the question.

  • Platform: Windows (and I'm not interested in portability)
  • Compiler: Microsoft's C++ compiler (I'm using VS2005)
  • Why I want to do this?: Using the ordinals has the advantage of letting me call exported C++ functions from C code.
+4  A: 

Well, I don't have experience with ordinals (which look like some ugly, compiler-specific thing), but I can help you with making C++/C code compatible.

Suppose, in C++, that your header file looks like this:

class MyClass
{
    void foo(int);
    int bar(int);
    double bar(double);
    void baz(MyClass);
};

You can make it C-compatible by doing the following:

#ifdef __cplusplus
#define EXTERN_C extern "C"
// Class definition here; unchanged
#else
#define EXTERN_C
typedef struct MyClass MyClass;
#endif

EXTERN_C void MyClass_foo (MyClass*, int);
EXTERN_C int MyClass_bar_int (MyClass*, int);
EXTERN_C double MyClass_bar_double (MyClass*, double);
EXTERN_C void MyClass_baz (MyClass*, MyClass*);

In the C++ source file, you just define the various extern "C" functions to pass to the desired member functions, like this (this is only one; the rest work similarly)

extern "C" void MyClass_foo (MyClass* obj, int i)
{
  obj->foo(i);
}

The code will then have a C interface, without having to change the C++ code at all (except for declarations in the header; but those could also be moved to another file "myclass_c.h" or the like). All the functions declared/defined extern "C" won't be mangled, so you can do other operations on them easily. You will also probably want functions to construct/destroy instances of MyClass (you can, of course, use new/delete for this).

coppro
+2  A: 

You said "Using the ordinals has the advantage of letting me call exported C++ functions from C code." , I am sorry to say that this is incorrect.

C++ class member functions have special calling convention which requires an invisible this value passed in an implementation-specific register/parameter. And also you need a class instance to pass, which you can not accomplish in C.

The only 2 uses of this that I know, are faster dynamic linking of the DLL and smaller Import Table. Just inspect mfc70.dll in system32 directory with the dependancy walker.

Malkocoglu
Isn't it possible to add the `this` value to the parameter list? And, if it can't be done directly... can I do it using the inline assembler?
Eduardo León
Well, anything is possible in "C" but I did not do such a thing. If it is possible, it will require non-portable constructs and/or ASM. So you better do everything in C++. The method proposed by coppro is also good, You just have to add MyClass_New and MyClass_Delete that uses void* for "this"...
Malkocoglu