unresolved metadata token when wrapping native DLL

  • Thread starter Thread starter David Kantowitz
  • Start date Start date
D

David Kantowitz

I am trying to wrap a native-C++ DLL in managed C++, to
use in a .NET project.

The native code is compiled into a DLL, and I have created
a .def file that exports the mangled names of the symbols
I am going to use from the wrapper library.

The wrapper library has the code written that uses the
native classes, and wraps them to present an equivalent of
their interface for .NET.

When I compile the managed-C++ wrapper library, everything
compiles fine, but upon linking I get a series of LNK2020
errors about unresolved tokens.

The help for this error suggests it is unable to resolve a
reference to the function that is in the metadata.

My wrapper project is set up to link against the import
library for the native DLL. When I do not link against
this library, I get the usual LNK2001 unresolved external
symbol. When I link against the import library, these go
away, but the LNK2020 appears.

Is it looking for metadata information in my native DLL,
or does it just mean that there is a reference in the
managed library's metadata that couldn't be resolved? In
either case, how do I go about resolving this?

Thanks in advance.

Regards,
David.
 
Hi David,

I am not sure what you mean by "The DLL I am trying to wrap contains C++
objects.", do you want to wrap C++ class or you instantiate C++ classes in
the unmanaged DLL?

Would you please post some code snippet of both unmanaged DLL and its
corresponding wrapper? Please also tell me the detailed error messages of
LNK2020 and LNK2001.

I look forward to hearing from you.

Have a nice day!

Regards,

HuangTM
Microsoft Online Partner Support
MCSE/MCSD

Get Secure! ¨C www.microsoft.com/security
This posting is provided ¡°as is¡± with no warranties and confers no rights.
 
The DLL contains the implementation of several C++
classes. These classes are what I am trying to wrap in my
managed-C++ DLL.

Here is an example of a class I am trying to wrap.

Unmanaged header:
#ifndef DEVICE_STATE_H
#define DEVICE_STATE_H
#include <SmartPtr.h>
#include <callback.h>

namespace Native {

class DeviceState
{
public:
DeviceState();
DeviceState(const DeviceState &);
~DeviceState();
DeviceState &operator=(const DeviceState &);

void set_bit(unsigned int bitpos, bool bval);
bool get_bit(unsigned int bitpos);

operator unsigned long() const;
SmartPtr<callback<bool> > create_callback(unsigned
long bitpos);

private:
class DeviceStateImpl;
DeviceStateImpl *impl;
};

}

#endif // DEVICE_STATE_H


Unmanaged implementation code (is compiled into the native
DLL):

#include <DeviceState.h>
#include <climits>
#include <algorithm>
#pragma warning(disable: 4127)
#include <bitset>

.... snip: some file-static utility functions ...

using Native::DeviceState;
DeviceState::DeviceState()
: impl(new DeviceStateImpl)
{
impl->ref_count = 1;
impl->Sync = new CriticalSection;
}

DeviceState::DeviceState(const DeviceState &other)
: impl(other.impl)
{
++impl->ref_count;
}

DeviceState &DeviceState::operator=(const DeviceState &rhs)
{
DeviceState temp(rhs);
std::swap(impl, temp.impl);
return *this;
}

DeviceState::~DeviceState()
{
if (0 == --impl->ref_count)
{
delete impl;
impl = 0;
}
}

void DeviceState::set_bit(unsigned int bitpos, bool bval)
{
impl->BitMask.set(bitpos, bval);
}

.... snip: more member function implementations ...


Managed code: This is in the header file:

private __gc class DeviceStateImpl;
public __gc class DeviceState
{
public:
DeviceState();
~DeviceState();

void SetBit(unsigned int bitpos, bool val);
bool GetBit(unsigned int bitpos);

__property void set_Bits(unsigned int bitpos, bool
val);
__property bool get_Bits(unsigned int bitpos);

private:
DeviceStateImpl *impl;
};


And this is the managed-C++ implementation of that class:

#include "stdafx.h"
#include "SNMPAgentLib.h" // managed header
#include "DeviceState.h" // native-code header

private __gc class DeviceStateImpl
{
public:
Native::DeviceState __nogc *state;
};

DeviceState::DeviceState()
: impl(new DeviceStateImpl)
{
impl->state = new Native::DeviceState;
}

DeviceState::~DeviceState()
{
delete impl->state;
}

void DeviceState::SetBit(unsigned int bitpos, bool val)
{
impl->state->set_bit(bitpos, val);
}

bool DeviceState::GetBit(unsigned int bitpos)
{
return impl->state->get_bit(bitpos);
}

void DeviceState::set_Bits(unsigned int bitpos, bool val)
{
SetBit(bitpos, val);
}

bool DeviceState::get_Bits(unsigned int bitpos)
{
return GetBit(bitpos);
}


The code compiles fine, but when linking yields messages
like this:

LINK : error LNK2020: unresolved token (0A0000A2)
Native.DeviceState.get_bit
LINK : error LNK2020: unresolved token (0A0000A3)
Native.DeviceState.set_bit
LINK : error LNK2020: unresolved token (0A0000A4)
Native.DeviceState.__dtor
LINK : error LNK2020: unresolved token (0A0000A5)
Native.DeviceState.__ctor

However, I can link against the same native-DLL's import
library from a non-managed C++ project and I get no link
errors, everything works fine.

I am wondering why it needs the metadata information for
the native code portion, and if there's anything I can do
to either fix my code or my project settings to satisfy
this.

Thanks.

Regards,
David.
 
Hello David,

To resolve the problem, you have to convert the managed DLL to mixed mode.
Please refer to the following MSDN document:

Converting Managed Extensions for C++ Projects from Pure Intermediate
Language to Mixed Mode
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vcmex/html/
vcconconvertingmanagedextensionsforcprojectsfrompureintermediatelanguagetomi
xedmode.asp

Hope this helps.

Regards,

HuangTM
Microsoft Online Partner Support
MCSE/MCSD

Get Secure! ¨C www.microsoft.com/security
This posting is provided ¡°as is¡± with no warranties and confers no rights.
 
Back
Top