Link errors - unresolved token/external symbol for unmanaged C++/CLI wrapper - c++-cli

So I have a wrapper shown below:
Wrapper.h
#pragma once
#include "Engine.h"
namespace Wrapper
{
public ref class EngineWrapper
{
public:
EngineWrapper();
virtual ~EngineWrapper();
protected:
!EngineWrapper();
private:
CEngine *m_engine;
};
}
Wrapper.cpp
#include "stdafx.h"
#include "Wrapper.h"
using namespace Wrapper;
EngineWrapper::EngineWrapper()
{
m_engine = new CEngine();
}
EngineWrapper::~EngineWrapper()
{
if (m_engine)
{
delete m_engine;
m_engine = NULL;
}
}
EngineWrapper::!EngineWrapper()
{
if (m_engine)
{
delete m_engine;
m_engine = NULL;
}
}
and this is some of my native engine code (in another project):
Engine.h
class CEngine
{
public:
CEngine();
virtual ~CEngine();
// other stuff
}
Engine.cpp
CEngine::CEngine()
{
// do stuff
}
CEngine::~CEngine()
{
// do stuff
}
My Wrapper project is a C++/CLI project compiled using /clr
My Engine project is a native C++ project which produces a .dll, .lib, and .exp (from looking at the output when this project builds)
For the Wrapper project, I've added the location of the native .lib to the linker input.
My issue: I get the following errors:
Error 126 error LNK2028: unresolved token (0A000380) "public: __thiscall
CEngine::CEngine(void)" (??0CEngine##$$FQAE#XZ) referenced in function "public:
__clrcall Wrapper::EngineWrapper::EngineWrapper(void)" (
0EngineWrapper#Wrapper##$$FQ$AAM#XZ) C:\..\..\Wrapper.obj Wrapper
Error 127 error LNK2019: unresolved external symbol "public: __thiscall
CEngine::CEngine(void)" (??0CEngine##$$FQAE#XZ) referenced in function "public:
__clrcall Wrapper::EngineWrapper::EngineWrapper(void)" (
0EngineWrapper#Wrapper##$$FQ$AAM#XZ) C:\..\..\Wrapper.obj Wrapper
As I think it is finding the library correctly, how come it doesn't recognize the native ctor?

Export the CEngine class in the native C++ project, check this URL for details

Related

WinRT C++ component with non primitive function return types fails to compile/build

The below program works fine while having functions with primitive return type functions specifically the Pop function defined below works and I'm able to build properly, but when I build the solution with a function having non primitive return type as in PopC like below project doesn't build, but definitions are syntatically correct and I'm able to see the types being referred properly with proper namespace definitions in pch.h file.
Have defined the below code in the StreamSamplePool.idl file,
namespace WinRTComponent
{
[default_interface]
runtimeclass StreamSamplePool
{
StreamSamplePool();
Int32 MyProperty;
// MediaStreamSample PopC();
Int32 Pop();
}
}
And inside the StreamSamplePool.cpp file have defined the respective methods as follows
#include "pch.h"
#include "StreamSamplePool.h"
#include "StreamSamplePool.g.cpp"
#include <stack>
#include <queue>
using namespace winrt::Windows::Storage::Streams;
using namespace winrt::Windows::Foundation;
using namespace std;
//using namespace Platform;
using namespace winrt::Windows::Media::Core;
namespace winrt::WinRTComponent::implementation
{
int32_t StreamSamplePool::MyProperty()
{
throw hresult_not_implemented();
}
int32_t StreamSamplePool::Pop()
{
return int32_t();
}
//MediaStreamSample StreamSamplePool::PopC()
//{
// MediaStreamSample sample = MediaStreamSample::CreateFromBuffer(NULL,
//TimeSpan());
// //sample.Processed += OnSampleProcessed;
// return sample;
//}
void StreamSamplePool::MyProperty(int32_t /* value */)
{
throw hresult_not_implemented();
}
}
And have defined the following code inside StreamSamplePool.h
namespace winrt::WinRTComponent::implementation
{
struct StreamSamplePool : StreamSamplePoolT<StreamSamplePool>
{
StreamSamplePool() = default;
int32_t Pop();
//MediaStreamSample PopC();
int32_t MyProperty();
void MyProperty(int32_t value);
};
}
namespace winrt::WinRTComponent::factory_implementation
{
struct StreamSamplePool : StreamSamplePoolT<StreamSamplePool,
implementation::StreamSamplePool>
{
};
}
Error info
Error MIDL2011 [msg]unresolved type declaration [context]: WinRTComponent.MediaStreamSample [ Procedure 'PopC' ( RuntimeClass
'WinRTComponent.StreamSamplePool' ) ] WinRTComponent D:\Prithvi\Work\WinRTComponent\StreamSamplePool.idl 9
Compiler output
1>D:\...\StreamSamplePool.idl(9): error MIDL2011: [msg]unresolved type declaration [context]: WinRTComponent.MediaStreamSample [ Procedure 'PopC' ( RuntimeClass 'WinRTComponent.StreamSamplePool' ) ]
1>Done building project "WinRTComponent.vcxproj" -- FAILED.
The issue can be reduced to the following IDL file:
namespace WinRTComponent
{
[default_interface]
runtimeclass StreamSamplePool
{
StreamSamplePool();
MediaStreamSample PopC();
}
}
Compiling this using a default-generated C++/WinRT Component project produces the following error:
1>C:\...\StreamSamplePool.idl(7): error MIDL2011: [msg]unresolved type declaration [context]: WinRTComponent.MediaStreamSample [ Procedure 'PopC' ( RuntimeClass 'WinRTComponent.StreamSamplePool' ) ]
It contains all the information required to resolve the issue. In particular it's naming the error ("unresolved type declaration"), and the procedure affected ("PopC"). To solve this you'll have to provide the fully-qualified type name in the IDL file, i.e.
namespace WinRTComponent
{
[default_interface]
runtimeclass StreamSamplePool
{
StreamSamplePool();
Windows.Media.Core.MediaStreamSample PopC();
}
}
With that done, go to the "Generated Files\sources" directory under the project root, and copy the respective parts of the "StreamSamplePool.h" and "StreamSamplePool.cpp" files that the build system generated to your source files.

Unresolved external symbol while not actually using the function

Given the following C++/CLI program:
#pragma managed(push, off)
class FooBar
{
FooBar(const FooBar& that) { *this = that; }
const FooBar& operator =(const FooBar& that);
};
#pragma managed(pop)
int main()
{
return 0;
}
Gives the following linker output:
Severity Code Description Project File Line Suppression State
Error LNK2019 unresolved external symbol "private: class FooBar const & __thiscall FooBar::operator=(class FooBar const &)" (??4FooBar##AAEABV0#ABV0##Z) referenced in function "private: __thiscall FooBar::FooBar(class FooBar const &)" (??0FooBar##AAE#ABV0##Z) ConsoleApplication1 C:\Users\SomeUser\Documents\Visual Studio 2019\Projects\ConsoleApplication1\ConsoleApplication1\ConsoleApplication1\ConsoleApplication1.obj 1
But the following C++ program does not:
class FooBar
{
FooBar(const FooBar& that) { *this = that; }
const FooBar& operator =(const FooBar& that);
};
int main()
{
return 0;
}
The reason I need this to work is because I'm including a header file which is beyond my control that does this. Although I never need to use the copy constructor or the assignment operator.
Compiled using v142 platform toolset.

How to use namespace System in a managed c++ reference class

I am trying to create managed C++ class by following this tutorial msdn.microsoft.com But while i tried to use namespace System System::String *_msg it always gives me an error that says
An ordinary pointer to a C++/Cli ref class or interface class is not
allowed
Hello.h
using namespace System;
ref class Hello
{
public:
System::String *_msg;
Hello(System::String *Msg);
};
hello.cpp File
#include "Hello.h"
using namespace System;
Hello::Hello(System::String *Msg)
{
Msg = _msg;
Console::WriteLine(Msg);
}
void main() {
Hello ^ h = gcnew Hello("hello world");
}
Instead of unmanaged * pointer use the managed pointer ^ sign:
using namespace System;
ref class Hello
{
public:
System::String ^_msg;
Hello(System::String ^Msg);
};
#include "Hello.h"
using namespace System;
Hello::Hello(System::String ^Msg)
{
Msg = _msg;
Console::WriteLine(Msg);
}
void main() {
Hello ^ h = gcnew Hello("hello world");
}

cpp/cli interop dll breaks in visual studio 2015

I've been assigned the task of upgrading an old interop dll into visualstudio2015 with the v140 toolset.
I'm getting an odd access violation now.
Exception thrown at 0x000007fef7d3d95c (mscoreei.dll) in HostApp.exe:
0xC0000005: Access violation reading location 0xffffffffffffffff
Did anything change in cpp/cli from v110 to v140?
I can tell the error occurs when the methods are defined in a separate cpp instead of inline in the Foo.h. This work-around isn't possible since this is where I need to call managed objects.
Here is my attempt at reconstructing the outline of the code:
shared header IFoo.h
#ifdef DLL_EXPORTS
#define __API__ __declspec(dllexport)
#else
#define __API__ __declspec(dllimport)
#endif
class IFoo
{
public:
__API__ static IFoo* Create();
virtual void DoSomething()=0;
};
Foo.h
#include IFoo.h
class Foo : public IFoo
{
public:
Foo() { } // if inline no crash
void DoSomething();
};
Foo.cpp
#include ManagedStuff.h
#include Foo.h
// Foo::Foo() { } // AV if not inline.
void Foo::DoSomething()
{
gcroot<ManagedClass^> stuff = gcnew ManagedClass();
.....
}
FooImpl.cpp
#include Foo.h
IFoo* IFoo::Create()
{
IFoo* f = new Foo(); // CRASH if ctor is NOT inline.
f->DoSomething(); //CRASH
return f;
}

Convert C++/CLI User Defined Object (%) to Native C++ object (&)

How can I convert a user defined object passed by (%) to a native object (&). For example
void managed_func(user_defined_managed_obj% m_obj_)
{
// i need this
obj_ptr->unmanaged_func(&m_obj_);
}
Thus, in the above example I would like to pass the managed object %m_obj_ to the argument of the unmanaged_func. Here user_defined_managed_obj is a .net wrapper in C++/CLI that is a bridge for a native C++.
I've tried the following:
pin_ptr<user_defined_unmanaged_obj> tmp_ptr = &m_obj_;
obj_ptr->unmanaged_func(*tmp_ptr);
Will someone point me into the right direction or let me know what I can do to remedy this problem. Thank you.
Edit:
The user_defined_unmanaged_obj is a native C++ object and the user_defined_managed_obj is the wrapper C++/CLI class for it.
Edit:
The following are the code
In native C++, native_sql.h
#include <string>
class native_sql
{
public:
native_sql(string arguments)
{...some codes}
~native_sql(void) = default;
void connect(void) {...some codes}
void clean(void) {...some codes}
}
In native C++, native_upload_specific_data.h
#include "native_sql.h"
#include <string>
class native_upload_specific_data
{
public:
native_upload_specific_data(string arugments) {...some codes}
~native_upload_specific_data(void)
void upload(native_sql& sql_obj_) {...some codes}
}
In C++/CLI, sql_wrapper.h
#include <msclr\marshal_cppstd.h>
#include "../native_sql.h"
#include "../native_sql.cpp"
using namespace System;
public ref class sql_wrapper
{
public:
sql_wrapper(String^ arguments)
{...codes to convert String^ to std::string and pass args to
new native_sql}
~sql_wrapper(void) { delete sql_ptr; }
void connect_wrapper(void) { sql_ptr->connect(); }
void clean_wrapper(void) { sql_ptr->clean(); }
native_sql* sql_ptr;
}
In C++/CLI wrapper, upload_specific_data_wrapper.h
#include "../native_upload_specific_data.h"
#include "../native_upload_specific_data.cpp"
using namespace System;
public ref class upload_specific_data_wrapper
{
public:
upload_specific_data_wrapper(String^ arguments)
{...convert String^ args into std::strings and pass to
native_upload_specific_data ctor}
~upload_specific_data_wrapper(void) { delete data_ptr; }
void upload(sql_wrapper% sql_obj_)
{
// here is where I have the problem
pin_ptr<native_sql*> ptr = &(sql_obj_.sql_ptr);
data_ptr->upload(ptr);
}
native_upload_specific_data* data_ptr;
}
The error I receive is
C2664: 'void native_upload_specific_data(native_sql&)': cannot convert arugment 1 from cli::pin_ptr<native_sql*> to native_sql&
....Thank you.