managed c to call an unmanaged c dll , unresolved token - c++

I have 1 native c++ dll, CppApp, another project is managed c++, GatWayLibrary, with /clr
In GatewayLibrary, I called functions from native CppApp dll.
but I got unresolve token errors.
Here are my code snips:
CppApp.h
=========
#ifdef CPPAPP_EXPORTS
#define CPPAPP_API __declspec(dllexport)
#else
#define CPPAPP_API __declspec(dllimport)
#endif
class CPPAPP_API CppApp
{
public:
CppApp();
~CppApp();
ContextManager & contextMgr() { return m_rplContextMng; }
INativeListener* m_listener;
void registerListener(INativeListener* listener)
{
m_listener = listener;
}
...........
}
In separate project, GateWaylibrary, wrap the native dll as
#include "../CppApp/CppApp.h"
#include <vcclr.h>
using namespace System;
using namespace System::Runtime::InteropServices;
#pragma comment(lib, "CppApp.lib")
namespace GatewayLibrary{
//.net equvelant of the argument class
public ref class DotNetEventArg{
internal:
//contructor takes native version of argument to transform
DotNetEventArg(const NativeCPPArgs& args) {
....
...
}
the managed c++ has the linking errors as unresolved tokens for all the function calls from the native c++.
I did include the CppApp.lib as Additional Dependencies
and the directory.
Can anyone please help? many thanks ahead.
Edit:
here is of the place I called the native c++
`GatewayLibrary::EventGateway::EventGateway()
{
nativeCode_ = new CppApp();
//note; using 'this' in ctor is not a good practice
nativeListener_ = new NativeListenerImp(this);
//register native listener
nativeCode_->registerListener(nativeListener_);
}`

Related

C++ dll in hololens

I am working creating a hololens application using a native code dll based on c ++. The problem comes when I add it in the unity project (plugins / WSA / x86).
When generating the UWP solution in Visual Studio I get a failure of DllNotFound.
From what I have been able to read, it is necessary to create a UWP library to use it in my application. That library must contain my native code. The truth is that I'm not sure how to do that. Is there any way to stop my dll based on c ++ on a UWP dll ??
error: System.DllNotFoundException: Unable to load DLL 'nativoHololensPrueba.dll': The specified module could not be found. (Exception from HRESULT: 0x8007007E).
C++
SOURCE:
#include <iostream>
#include <stdio.h>
#include <memory>
#include "Header.h"
__declspec(dllexport)
int testo() {
return 10;
}
HEADER:
extern "C" {
__declspec(dllexport)
int testo();
}
c#
[DllImport("nativoHololensPrueba")]
public static extern int testo();
// Use this for initialization
public GameObject texto;
void Start () {
texto.GetComponent<TextMesh>().text = "Cambiando el nombre " + testo();
}
I also had this and I solved it by compiling the dll on ARM64 (or ARM) with /MT flag.

Use C++/CLI Library in C++ native code and how to link

I want to use some code that executes a http-post, and because I'm not too familiar with c++ and what libraries you can use, and I am probably too dumb to get libcurl and curlpp to work, I found a link explaining how to use the .net version.
Alright so I created a class. Header File:
public ref class Element
{
public:
Element();
virtual ~Element();
void ExecuteCommand();
};
Class file:
#include "Element.h"
Element::Element()
{
}
Element::~Element()
{
Console::WriteLine("deletion");
}
void Element::ExecuteCommand(){
HttpWebRequest^ request = dynamic_cast<HttpWebRequest^>(WebRequest::Create("http://www.google.com"));
request->MaximumAutomaticRedirections = 4;
request->MaximumResponseHeadersLength = 4;
request->Credentials = gcnew NetworkCredential("username", "password", "domain");
HttpWebResponse^ response = dynamic_cast<HttpWebResponse^>(request->GetResponse());
Console::WriteLine("Content length is {0}", response->ContentLength);
Console::WriteLine("Content type is {0}", response->ContentType);
// Get the stream associated with the response.
Stream^ receiveStream = response->GetResponseStream();
// Pipes the stream to a higher level stream reader with the required encoding format.
StreamReader^ readStream = gcnew StreamReader(receiveStream, Encoding::UTF8);
Console::WriteLine("Response stream received.");
Console::WriteLine(readStream->ReadToEnd());
response->Close();
readStream->Close();
}
If I set the configuration type of this project to Application (exe), and create a new .cpp file where I create an Instance of this Element it works fine.
But my question is: Is it possible to create a .dll/.lib Library from this project and use it in a C++ project without CLI? (I don't want to use ^ for pointers :( )
Even if it's not possible, I have another problem.
When I link the library in a C++/CLI project. I get
unresolved token (06000001) Element::.ctor
unresolved token (06000002) Element::~Element
unresolved token (06000003) Element::ExecuteCommand
3 unresolved externals
the code for main.cpp in the second project is just the following:
#include <Element.h>
int main(){
return 0;
}
Thank you
As Hans Passant already stated: you must compile your C++/CLI code as Dynamic Library in order to be able to consume it from an unmanaged application. CLI/Managed code cannot run from/cannot reside in static libraries.
If you change the C++/CLI library target from Static library to Dynamic library you'll be able to compile successfully your unmanaged C++ application.
One thought from my side:
I think you'll be better if you use mixed mode C++/CLI DLLs to consume the managed functionality - you'll be able to free your consumer application completely from referencing the CLR.
The Header of such mixed mode Wrapper for your Element class would look like this:
#pragma once
#pragma unmanaged
#if defined(LIB_EXPORT)
#define DECLSPEC_CLASS __declspec(dllexport)
#else
#define DECLSPEC_CLASS __declspec(dllimport)
#endif
class ElementWrapperPrivate;
class __declspec(dllexport) ElementWrapper
{
private:
ElementWrapperPrivate* helper;
public:
ElementWrapper();
~ElementWrapper();
public:
void ExecuteCommand();
};
And the implementation would look like this:
#include "ElementWrapper.h"
#pragma managed
#include "Element.h"
#include <msclr\auto_gcroot.h>
using namespace System::Runtime::InteropServices;
class ElementWrapperPrivate
{
public:
msclr::auto_gcroot<Element^> elementInst; // For Managed-to-Unmanaged marshalling
};
ElementWrapper::ElementWrapper()
{
helper = new ElementWrapperPrivate();
helper->elementInst = gcnew Element();
}
ElementWrapper::~ElementWrapper()
{
delete helper;
}
void ElementWrapper::ExecuteCommand()
{
helper->elementInst->ExecuteCommand();
}
Then just compile your Element.cpp + ElementWrapper.cpp to a DLL and use the ElementWrapper.h in your unmanaged applications.

How to make a managed (clr) multithreaded c++ .dll?

I am trying to make a managed .dll in c++ that requires the support for multithreading. I am developing in visual Studio 2013, using platform toolset version v120. the reason I need this to be a managed assembly is because it is required to integrate the assembly in LabView.
following the steps in Creating and Using a Managed Assembly in VC++ 2010 gives good results. but I obviously need to implement something more complicated and when I include threading and write the following code:
#pragma once
#include <thread>
using namespace System;
using namespace std;
namespace MultiThread_module {
public ref class multiThreadingTest
{
public:
String^ GetVersion();
int someNumber;
private:
thread testThread;
};
}
I get following errors:
"thread" is not supported when compiling with /clr or /clr:pure.
a member of a managed class cannot be of a non-managed class type
error directive: ERROR: Concurrency Runtime is not supported when
compiling /clr.
error directive: is not supported when compiling with /clr or
/clr:pure.
A friend of mine says it is impossible to write multi-threaded code in Visual Studio without using external packages like boost. It kind of seemed unlikely since Multithreading has already been already there for C# and VB for a long time!
So, I would be happy if you could let me know what I am doing wrong OR if it is really hard to have a managed multithreaded .dll developed in c++?
You can use the managed thread library: System.Threading.Thread.
#pragma once
using namespace System;
using namespace std;
using namespace System::Threading;
namespace MultiThread_module {
public ref class multiThreadingTest
{
public:
String^ GetVersion();
int someNumber;
private:
Thread^ testThread;
};
}
If it's purely CLR then I suggest you use the example provided before. If you want to have the threading completely native and just use CLR to wrap it, I'd like to refer you to my answer at : using clr and std::thread
Might be an old question, but I looked into this same problem before. Since CLR does not allow you to include std::thead at
compile time, you could try to use it only at linking time. Normally
you could resolve this be forward declaring the class in your header
and including them only in your cpp files. However you can forward
declare your own classes in header files, but you can't for
classes in namespace std. According to the C++11 standard, 17.6.4.2.1:
The behavior of a C++ program is undefined if it adds declarations or
definitions to namespace std or to a namespace within namespace std
unless otherwise specified.
A workaround for this problem is to create a threading class that
inherits from std::thread that you can forward declare. The header
file for this class would look like:
#pragma once
#include <thread>
#include <utility>
namespace Threading
{
class Thread : std::thread
{
public:
template<class _Fn, class... _Args> Thread(_Fn fn, _Args... args) : std::thread(fn, std::forward<_Args...>(args...))
{
}
private:
};
}
In the header file that you would like to use the thread you can do
forward declare it like:
#pragma once
// Forward declare the thread class
namespace Threading { class Thread; }
class ExampleClass
{
public:
ExampleClass();
void ThreadMethod();
private:
Threading::Thread * _thread;
};
In your source file you can then use the theading class like:
#include "ExampleClass.h"
#include "Thread.h"
ExampleClass::ExampleClass() :
{
_thread = new Threading::Thread(&ExampleClass::ThreadMethod, this);
}
void ExampleClass::ThreadMethod()
{
}
Hope it might help anyone.

Using native C libraries in dot42

Is it possible to use a native C/C++ library with dot42? If so are there examples of how to do this? If not is this a planned feature?
Given the JNI implementation a native method such as the following:
#include <string.h>
#include <jni.h>
jstring Java_dllImportTest_MainActivity_Foo( JNIEnv* env, jobject thiz)
{
return (*env)->NewStringUTF(env, "Hello from dot42 JNI !");
}
The JNI tooling will compile this to a native library and put this in e.g. libs\armeabi.
Copy the libs folder to the root of your dot42 project and include the .so in your project. Next set the build action to NativeCodeLibrary:
Next declare the native method in your C# code using the DllImport attribute and call it like this:
using System;
using System.Runtime.InteropServices;
using Android.App;
using Android.Os;
using Android.Widget;
using Dot42;
using Dot42.Manifest;
[assembly: Application("DllImportTest")]
namespace DllImportTest
{
[Activity(Label ="DllImport MainActivity")]
public class MainActivity : Activity
{
protected override void OnCreate(Bundle savedInstance)
{
base.OnCreate(savedInstance);
SetContentView(R.Layouts.MainActivityLayout);
var textView = FindViewById<TextView>(R.Ids.label);
textView.Text = Foo();
}
[DllImport("dllImportTest")]
public static extern string Foo();
}
}
The loadLibrary call is generated by the dot42 compiler.

Passing unmanaged C++ object into managed C++ code

So as the title states, I am looking to pass an object that is defined in an unmanaged C++ project into a managed C++/CLI project (both projects are in the same solution) while still being able to access the same methods as in the unmanaged C++ project.
This object is a class which imports functions from a separate unmanaged C++ dll (not in the same project or solution) through the means of using typedef's as shown below (excerpt of header):
#pragma unmanaged
typedef BOOL (WINAPI *someBoolFunc) (DWORD Name, DWORD Flags, TCHAR* Text);
class INeedThisClass
{
public:
INeedThisClass();
~INeedThisClass();
someBoolFunc BoolFunc;
};
extern INeedThisClass ReallyNeedThisClass;
I would really like to be able to access the externed object ReallyNeedThisClass from within my managed code by just only passing the object. By having this object I wish to access it's methods through ReallyNeedThisClass->BoolFunc. What is the best way of accessing this object from my managed code?
EDIT: I've been thinking maybe there is a way of using a property to "Get" the object from the unmanaged code and then "Set" the same object in the managed code. Could this be a proper angle to approach this issue from? I've cleaned up the question a bit to get rid of useless details.
UPDATE: I've made progress on this using a wrapper for the unmanaged C++ code, but of course there are still problems. Using the above class as an example here, I will show you what I have managed to do up until now.
Project 1: Unmanaged C++ class (example above)
Project 2: Managed C++/CLR wrapper class (example below)
Wrapper.h:
#pragma once
#include "INeedThisClass.h" //Unmanaged class INeedThisClass
using namespace System;
using namespace System::Runtime::InteropServices;
namespace INeedThisClassWrapper
{
public ref class INTC
{
public:
INTC(void);
virtual ~INTC(void);
delegate bool BoolFunc(UInt32 Name, UInt32 Flags, String^ Text);
private:
INeedThisClass *ReallyNeedThisClass;
};
}
Wrapper.cpp:
#include "Stdafx.h"
#include "Wrapper.h"
using namespace INeedThisClassWrapper
#include <msclr/marshal.h>
using namespace msclr::interop;
INTC::INTC(void)
{
ReallyNeedThisClass = new INeedThisClass();
}
INTC::~INTC(void)
{
if (ReallyNeedThisClass)
{
delete ReallyNeedThisClass;
ReallyNeedThisClass = NULL;
}
}
bool INTC::BoolFunc(UInt32 Name, UInt32 Flags, String^ Text)
{
return ReallyNeedThisClass->BoolFunc;
}
Now I am receiving errors from the compiler stating:
error C2065: 'WINAPI': undeclared identifier
error C2065: 'someBoolFunc': undeclared identifier
error C4430: missing type specifier - int assumed. Note C++ does not support default-int
Any ideas?
First, you have to export INeedThisClass from unmanaged dll and import from managed one.
//unmanaged header
#if UNMANAGED_COMPILE_DEFINITION
#define EXPORT_OR_IMPORT __declspec(dllexport)
#else
#define EXPORT_OR_IMPORT __declspec(dllimport)
#endif
class EXPORT_OR_IMPORT INeedThisClass
{
public:
INeedThisClass();
~INeedThisClass();
someBoolFunc BoolFunc;
};
Also unmanaged dll must be compiled with UNMANAGED_COMPILE_DEFINITION preprocessor definiton.
Second, remove extern INeedThisClass ReallyNeedThisClass; you don't need it. Because ReallyNeedThisClass is a member of wrapper class already.
Third, you need to marshal System::String^ to TCHAR* in order to call BoolFunc
Forth, I do not remember but if you include "Windows.h" or "Winnt.h", the error about WINAPI will be gone.