Managed vc++ 2003 compile problem

Hello, i've got a really anoying bug that i cant seem to figure out.. The code comes from a 2005 project which needs to be compiled in a 2003 project. The code is as follows:

// CitectAPIManagedDll.h

#pragma once

using namespace System;
using namespace System::Runtime::InteropServices;

namespace CitectAPIManagedDll
{
/// Create a unmanaged wrapper structure as the placeholder for unmanaged class
/// members as exported by the DLL. This structure/class is not intended to be
/// instantiated by .NET applications directly.
public __gc struct CitectAPIUnman
{
/// Define the virtual table for the wrapper
typedef __gc struct __VTB
{
void (*Open)(CitectAPIUnman*, System::String*, System::String*, System::String*, System::Int32*);
};

public:
char* id;
static __VTB *vtb;

/// Perform all required imports. Use "ThisCall" calling convention to import
/// functions as class methods of this object (not "StdCall"). Note that we
/// pass this pointer to the imports. Use the "decorated name" instead of
/// retreived from the DLL as the entry point.
[DllImport("CTAPI.dll",
EntryPoint="ctOpen",
CallingConvention=CallingConvention::ThisCall)]
static void Open(CitectAPIUnman*, System::String*, System::String*, System::String*, System::Int32*);

/// Delegates of imported virtual methods for the virtual table.
/// This basically is hacking the limitation of function pointer (FP),
/// as FP requires function address at compile time.
static void VOpen(CitectAPIUnman* w, System::String* computer, System::String* username, System::String* password, System::Int32* mode)
{
Open(w, computer, username, password, mode);
}
};

/// Managed wrapper class which will actually be used by .NET applications.
public __gc class CitectAPIWrap
{
public:
/// User-defined managed wrapper constructor. It will perform a few tasks:
/// 1) Allocating memory for the unmanaged data
/// 2) Assign the v-table
/// 3) Marshall the parameters to and call the imported unmanaged class constructor
CitectAPIWrap()
{
tv = new CitectAPIUnman();
CitectAPIUnman::vtb->Open = CitectAPIUnman::VOpen;
}

/// Let the v-table handle method overriding
virtual void Open(System::String* computer, System::String* username, System::String* password, System::Int32* mode)
{
CitectAPIUnman::vtb->Open(tv, computer, username, password, mode);
}

private:
CitectAPIUnman *tv;
};
}

i get the following compile error in my header file:
error C2440: '=' : cannot convert from 'void (__clrcall CitectAPIManagedDll::CitectAPIUnman::* )(CitectAPIManagedDll::CitectAPIUnman __gc *,System::String __gc *,System::String __gc *,System::String __gc *,int __gc *)' to 'void (__clrcall *)(CitectAPIManagedDll::CitectAPIUnman __gc *,System::String __gc *,System::String __gc *,System::String __gc *,int __gc *)'

my cpp file is as follows:

// This is the main DLL file.

#include "stdafx.h"

#include "CitectAPIManagedDll.h"

using namespace CitectAPIManagedDll;

/// Unmanaged wrapper static data initialization
CitectAPIUnman::__VTB *CitectAPIUnman::vtb = new CitectAPIUnman::__VTB;

i get the following compile error in my cpp file:
.\CitectAPIManagedDll.cpp(10) : error C2374: 'vtb' : redefinition; multiple initialization
c:\pas\source code\database\citectapimanaged_2003\citectapimanageddll\CitectAPIManagedDll.h(23) : see declaration of 'vtb'
.\CitectAPIManagedDll.cpp(10) : error C3366: 'CitectAPIManagedDll::CitectAPIUnman::vtb' : static data members of managed types must be defined within the class definition


any ideas this is the first time ive used 2003 to compile this project. your help is greatly appreciated.

thanks.



Answer this question

Managed vc++ 2003 compile problem

  • americanDesi

    To be honest there is so much wrong with this piece of code it is hard to know where to start: it is meant to be declaring a typedef but a typedef to what If Visual C++ 2005 (or Visual C++ 2003) compile this code as-is then I am really embarassed.

  • Filthysock

    Thanks for your help so far. However, from my perspective this looks like working code.. (this is my first time using 2003.. i usually code in 2005)..

    any suggestions on what that piece of code should look like

    Thanks again. your helps really appreciated.


  • ngn

    Unfortunately I don't have Visual C++ 2003 available - but if I change '^' to '*' it compiles with Visual C++ 2005 if I use the /clr:oldSyntax switch. Note: using a typedef to give an unnamed class a name is so C-89 passe - this is C++ just give the class a real name.

  • S.Kannan

    I'm not 100% sure what is going on here but this code definitely looks suspect:

    typedef __gc struct __VTB
    {
    void (*Open)(CitectAPIUnman*, System::String*, System::String*, System::String*, System::Int32*);
    };



  • FransHals

    i originally had was vc++ 2005. it compiled fine.

    The current code i have posted is adapted from my original vc++ 2005 code. i have removed the various vc++ 2005 specific syntax references (eg. int^ x) and changed it to vc++ 2003 compliant syntax... i almost got it compiling in vc++ 2003 but i have those 2 compile bugs to fix.

    my original 2005 code looked like this:

    // CitectAPIManagedDll.h

    #pragma once

    using namespace System;
    using namespace System::Runtime::InteropServices;

    namespace CitectAPIManagedDll
    {
    /// Create a unmanaged wrapper structure as the placeholder for unmanaged class
    /// members as exported by the DLL. This structure/class is not intended to be
    /// instantiated by .NET applications directly.
    public struct CitectAPIUnman
    {
    /// Define the virtual table for the wrapper
    typedef struct
    {
    void (*Open)(CitectAPIUnman*, String^, String^, String^, Int32^);
    } __VTB;

    public:
    char* id;
    static __VTB *vtb;

    /// Perform all required imports. Use "ThisCall" calling convention to import
    /// functions as class methods of this object (not "StdCall"). Note that we
    /// pass this pointer to the imports. Use the "decorated name" instead of
    /// retreived from the DLL as the entry point.
    [DllImport("CTAPI.dll",
    EntryPoint="ctOpen",
    CallingConvention=CallingConvention::ThisCall)]
    static void Open(CitectAPIUnman*, String^, String^, String^, Int32^);

    /// Delegates of imported virtual methods for the virtual table.
    /// This basically is hacking the limitation of function pointer (FP),
    /// as FP requires function address at compile time.
    static void VOpen(CitectAPIUnman* w, String ^computer, String ^username, String ^password, Int32 ^mode)
    {
    Open(w, computer, username, password, mode);
    }
    };

    /// Managed wrapper class which will actually be used by .NET applications.
    public ref class CitectAPIWrap
    {
    public:
    /// User-defined managed wrapper constructor. It will perform a few tasks:
    /// 1) Allocating memory for the unmanaged data
    /// 2) Assign the v-table
    /// 3) Marshall the parameters to and call the imported unmanaged class constructor
    CitectAPIWrap()
    {
    tv = new CitectAPIUnman();
    CitectAPIUnman::vtb->Open = CitectAPIUnman::VOpen;
    }

    /// Let the v-table handle method overriding
    virtual void Open(String ^computer, String ^username, String ^password, Int32 ^mode)
    {
    CitectAPIUnman::vtb->Open(tv, computer, username, password, mode);
    }

    private:
    CitectAPIUnman *tv;
    };
    }

    as you can see, there are various things in the above code that wont compile in 2003.. eg, 2003 needs the __gc code for managed code..

    my understanding is 2003 compilant code will compile in 2005.. i need to rewrite this above code to compile in 2003.

    thanks heaps for your help.


  • Managed vc++ 2003 compile problem