Unity3D call external dll - c#

I am trying to build a native plugin for Unity3D Pro (5.0). So far, I have built a DLL file in VS express 2013 for Windows, I have created a sample Unity project just for that and linked the library, but I am still getting an error and I cannot seem to move. Google wasn't very helpful in that matter ...
I am trying to add a DLL with my own low-level stuff for Windows Store target.
The stuff I am trying to access this way doesn't matter, I am stuck at hello world example app.
Visual Studio project
Dll3.cpp
#include "pch.h"
#include "Dll3.h"
extern "C" __declspec(dllexport) int testFunc(int a, int b) {
return a + b;
}
Dll3.h
#pragma once
using namespace std;
extern "C" __declspec(dllexport) int testFunc(int a, int b);
dllmain.cpp
#include "pch.h"
BOOL APIENTRY DllMain(HMODULE /* hModule */, DWORD ul_reason_for_call, LPVOID /* lpReserved */)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
pch.h
#pragma once
#include "targetver.h"
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#endif
// Windows Header Files:
#include <windows.h>
pch.cpp
#include "pch.h"
and I set the build target to x64, the DLL file exported successfully without any errors or warnings.
Unity Project
I plopped the Dll3.dll file to the Assets/ folder. At first, I had it in Assets/Plugins/ but I figured out it didn't matter at all.
test.cs
using UnityEngine;
using System.Collections;
using System.Runtime.InteropServices;
public class test : MonoBehaviour {
// Dll import according to Unity Manual
#if UNITY_IPHONE || UNITY_XBOX360
[DllImport ("__Internal")]
#else
[DllImport ("Dll3")]
#endif
private static extern int testFunc (int a, int b);
// Use this for initialization
void Start () {
int a = 1;
int b = 2;
int c = testFunc (a, b);
Debug.Log (c.ToString ());
}
// Update is called once per frame
void Update () {
}
}
Then I created an empty game object, assigned this script to it, compiled and run. It compiled without any errors or warnings, but when running (in Editor), I got this:
Failed to load 'Assets/Dll3.dll' with error 'This operation is only valid in the context of an app container.', GetDllDirectory returned ''. If GetDllDirectory returned non empty path, check that you're using SetDirectoryDll correctly.
Failed to load 'Assets/Dll3.dll' with error 'This operation is only valid in the context of an app container.', GetDllDirectory returned ''. If GetDllDirectory returned non empty path, check that you're using SetDirectoryDll correctly.
DllNotFoundException: Assets/Dll3.dll
test.Start () (at Assets/test.cs:18)
Can anyone, please point me to where I am doing the mistake? I am used to Unix (OSX/Linux) environment and Windows very non-standard for me. I do not understand completely the concept of the VS DLL project. I would be grateful for any help. Thank you

Yeah, it was correct from the start. I just needed to run it in Visual Studio Simulator, as a Store App on my desktop or deploy it to my development tablet PC. It does NOT run in the Unity Editor - I am such a fool :-)

Related

Calling C++ DLL from C# is ok under Windows 7 but fails under Windows 10

My program calls a C++ DLL from my C# program.
The problem is that the generated executable is running fine undex Windows 7 but not under Windows 10 !?
The steps are listed below:
I compile my C++ DLL using g++ (of TDM-GCC-64) in 64 bits.
I compile my C# program using Visual studio 15 and target .NET framework 4.5.2 in 64 bits.
The C++ DLL code is :
main.h
#ifndef __MAIN_H__
#define __MAIN_H__
#include <windows.h>
/* To use this exported function of dll, include this header in your project. */
#ifdef BUILD_DLL
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT __declspec(dllimport)
#endif
#ifdef __cplusplus
extern "C"
{
#endif
void DLL_EXPORT SomeFunction(const LPCSTR sometext);
#ifdef __cplusplus
}
#endif
#endif // __MAIN_H__
main.cpp
#include "main.h"
#include <iostream>
// a sample exported function
void DLL_EXPORT SomeFunction(const LPCSTR sometext)
{
std::cout << "TEST FROM DLL : " << sometext << std::endl;
}
The build command is :
C:\TDM-GCC-64\bin\g++ -shared -o ..\TestDllCall\bin\x64\Debug\myDLL.dll -m64 -g -D BUILD_DLL -L. main.cpp
You can notice that the dll is created directly in the target directory of the c# test program (Debug in 64 bits).
The C# main program is:
Program.cs
using System;
using System.IO;
using System.Runtime.InteropServices;
namespace TestHstLibrary
{
class MainProg
{
static void Main(string[] args)
{
ProgramTest ProgramTest = new ProgramTest();
ProgramTest.dllCall();
Console.ReadKey();
}
}
class ProgramTest
{
[DllImport("myDLL.dll", EntryPoint = "SomeFunction")]
static extern void SomeFunction(string sometext);
public ProgramTest() {
}
public void dllCall()
{
Console.WriteLine("dllCall ... ");
try
{
SomeFunction("Hello !");
} catch (Exception e)
{
Console.WriteLine("EXCEPTION : " + e.Message);
Console.WriteLine(e.ToString());
}
Console.WriteLine("");
}
}
}
Note : The build is done on the final target plateform : Win10 64bits.
Running on my Windows 10, I have the following :
dllCall ...
EXCEPTION : Unable to load DLL 'myDLL.dll': A dynamic link library (DLL) initialization routine failed. (Exception from HRESULT : 0x8007045A)
System.DllNotFoundException: Unable to load DLL 'myDLL.dll': A dynamic link library (DLL) initialization routine failed. (Exception de HRESULT : 0x8007045A)
à ProgramTest.SomeFunction(String sometext)
à ProgramTest.dllCall() dans C:\TestDllCall\TestDllCall\Program.cs:ligne 30
After a copy of the entire build directory from Win10 to a Win7,
running it on my Win7, I have the following :
dllCall ...
TEST FROM DLL : Hello !
It's working fine.
If someone has an idea why it fails under Win10 and not under Win7, I will be pleased to have the answer.
I check with dependency walker and had the following:
- Under Windows 10, some dependencies are missing even if it has been generated under Win10
- Under Windows 7, all dependencies are ok.
So I try with an other c++ compiler from g++ of TDM-GCC-64, I tested with the one from cygwin : does not give a better result, even worse.
I also try to pass my c# string parameter as a IntPtr as shown below:
IntPtr myptr = Marshal.StringToHGlobalAnsi("Hello !");
SomeFunction(myptr);
But it does not work either under Win10 but still working under Win7.
An other test was to remove the std::cout form my dll, finally the call is ok but I still want to make it work as this is in a test environment and in a production environment I will have to make it with an external dll which I don't have the source code.
I updated the code as below :
int DLL_EXPORT SomeFunction()
{
return 5;
}
It was working. So called unmanaged dll from c# is ok.
After, I search about the cout, I found in stackoverflow some topic related to usage of cout in unmanaged dll called from c# ...
So after I changed again the function to the following :
void DLL_EXPORT SomeFunction(const LPCSTR sometext)
{
MessageBoxA(0, sometext, "DLL Message", MB_OK | MB_ICONINFORMATION);
}
The error happens again !
Then I decided after some advice while triyng to solve this problem to build the DLL with Visual Studio C++ (instead of TDM-GCC-64).
After building the DLL with MS C++ and running the test under Win10: It's working :-)
The std::cout is OK
The messageBox is OK
There is no more : Exception from HRESULT : 0x8007045A
Thanks a lot to people who answered.

Unmanaged C++ wrapper for C# usage

SOLVED: Thanks to Casey Price for their answer. I then ran into 2 other errors: BadImageFormatException and FileNotFoundException, the former was solved by matching the platform target (x64 or x86) for each project and the latter was solved by setting the output directory of the C# project to the directory containing the dll file.
I'm working on a game 'engine' which currently has a working graphics subsystem that draws/textures movable models. I'm trying to write a C++/CLR wrapper so I can use the engine in a C# program (as a designer tool).
My wrapper project is a C++/CLR class library and contains the following 2 files (as well as resource.h/cpp and Stdafx.h/cpp)
// pEngineWrapper.h
#pragma once
#define null NULL
#include "..\pEngine\pEntry.h"
using namespace System;
namespace pEngineWrapper
{
public ref class EngineWrapper
{
public:
EngineWrapper();
~EngineWrapper();
bool Initialise();
private:
pEntry* engine;
};
}
and the .cpp file
// This is the main DLL file.
#include "stdafx.h"
#include "pEngineWrapper.h"
pEngineWrapper::EngineWrapper::EngineWrapper()
{
engine = null;
}
pEngineWrapper::EngineWrapper::~EngineWrapper()
{
delete engine;
engine = null;
}
bool pEngineWrapper::EngineWrapper::Initialise()
{
bool result;
engine = new pEntry;
result = engine->Initialise();
if( result == false )
{
return false;
}
return true;
}
When I go to build this project however I get 14 errors: LNK2028, LNK2019, and LNK2001 which points to some classes within the engine. I have included the errors in the file below.
https://www.dropbox.com/s/ewhaas8d1te7bh3/error.txt?dl=0
I also get a lot of warnings regarding XMFLOAT/XMMATRIX which you may notice.
In all of the engine classes I use the dllexport attribute
class __declspec(dllexport) pEntry
I feel like I'm missing the point and doing it all wrong seeing all of these errors but I haven't found any documents telling me anything considerably different than what I'm doing here
you have to add a reference to the static .lib files for the game engine you are using as well as it's dll's or load the dll's manually
to add the references to the .lib files right click your project->Properties->Linker->input add the lib file to the additional dependencies
See also: DLL References in Visual C++

Wrapping C++ CLI Class For C#

I'm trying to call some Windows basic functions from C#, in particular this one.
Since the moment I want to learn the C++/CLI Language too, I've written down this code:
#pragma once
#include <string>
#include <Windows.h>
using namespace System;
namespace InformazioniSchermo {
public class Native_InformazioniDaSistema
{
public:
int m_nAltezzaPannello;
int m_nLarghezzaPannello;
Native_InformazioniDaSistema(void)
{
DISPLAY_DEVICE dd;
DWORD dev = 0;
dd.cb = sizeof(dd);
EnumDisplayDevices(0, dev, &dd, 0);
m_nAltezzaPannello = 100;
m_nLarghezzaPannello = 100;
}
};
public ref class InformazioniDaSistema
{
public:
InformazioniDaSistema();
~InformazioniDaSistema();
public:
int m_nHeight;
int m_nWidth;
};
InformazioniDaSistema::InformazioniDaSistema()
{
Native_InformazioniDaSistema foo;
m_nHeight = foo.m_nAltezzaPannello;
m_nWidth = foo.m_nLarghezzaPannello;
}
InformazioniDaSistema::~InformazioniDaSistema()
{
}
}
but when I compile, I get this error:
Error 3 error LNK2028: at unresolved token (0A0003B4) "extern "C" int __stdcall EnumDisplayDevicesW(wchar_t const *,unsigned long,struct _DISPLAY_DEVICEW *,unsigned long)" (?EnumDisplayDevicesW##$$J216YGHPB_WKPAU_DISPLAY_DEVICEW##K#Z) referencing in function "public: __thiscall InformazioniSchermo::Native_InformazioniDaSistema::Native_InformazioniDaSistema(void)" (??0Native_InformazioniDaSistema#InformazioniSchermo##$$FQAE#XZ) c:\Users\massimiliano\documents\visual studio 2013\Projects\InformazioniSchermo\InformazioniSchermo\InformazioniSchermo.obj InformazioniSchermo
Where am I doing wrong?
You need to link against user32.lib (the library for the EnumDisplayDevices function, as you'll see in the MSDN page you linked to).
You can do this by going to project properties->Linker->Input and adding user32.lib to the "Additional Dependencies" list.
I notice that the default Visual Studio project settings for C++/CLI don't include the common Windows API libraries by default (regular C++ projects have kernel32.lib, user32.lib, shell32.lib and others added to the project's library dependencies in new projects) so you have to add these libraries yourself if you're using them.
error LNK2028: ... (?EnumDisplayDevicesW##$$J216YGHPB_WKPAU_DISPLAY_DEVICEW##K#Z) ...
That is the name the linker is looking for. That is not it's name, it is a C function and does not have the C++ name mangling. Pretty unclear how you did that, especially since you obfuscated your #includes. But the only reasonable guess is that you declared this function yourself instead of using its declaration in the SDK header.
Never do that. Instead use:
#include <Windows.h>
#pragma comment(lib, "user32.lib")
With the #pragma helpful so you can't forget to link to user32

Creating a CPP DLL for use in a C# program

So I have a WPF solution. I added a new project and added a CPP Dll project to it.
I used this example. Pretty straight forward.
http://www.codeproject.com/Articles/9826/How-to-create-a-DLL-library-in-C-and-then-use-it-w
Here is my code
CppTestDll.cpp
#include <stdio.h>
extern "C"
{
__declspec(dllexport) void DisplayHelloFromDLL()
{
printf("Hello from DLL !\n");
}
}
When I build this I do in fact get a DLL
Now when I go into my WPF app and attempt to add a reference to this DLL I get this error.
"A reference to 'C:\DIR\testcppdll.dll' could not be added. Please
make sure that the file is accessible, and that it is a valid assembly
or COM component."
If you look in the example you cite:
Creating a simple C# application:
Start Visual Studio .NET. Go to File->New->Project.
Select Visual C#
Project. ... (you can select WPF Project)
Give the name to your application. Press OK. Into the specified
class, insert the following two lines:
[DllImport("TestLib.dll")]
public static extern void DisplayHelloFromDLL ();
In C#, keyword extern indicates that the method is implemented externally.
Your code should look something like this:
using System;
using System.Runtime.InteropServices; // DLL support
class HelloWorld
{
[DllImport("TestLib.dll")]
public static extern void DisplayHelloFromDLL ();
public void SomeFunction()
{
Console.WriteLine ("This is C# program");
DisplayHelloFromDLL ();
}
}
You don't add a reference to the to the DLL - you P/Invoke the Function using DLLImport

How do i create a namespace and constructor in c++ in a dll project?

I created on my visual studio 2012 pro a new dll project and the main .cpp file is empty except this line:
#include "stdafx.h"
In this dll project I have a new c language item(module) I added with some functions inside.
In fact I want to create in my main .cpp file some functions that will call the function from the c item(module).
For example in the .cpp file I will have something like this:
void start()
{
encoder.start();
}
Then in the .cpp I need to add a constructor so I can call there the start()
How should I do it ?
Here is an example in my solution i have two projects one console application one dll.
This is the content of the main cpp file from the console application project:
#include "stdafx.h"
#include "targetver.h"
extern "C" {
void video_encode_example(const char *filename);
}
int _tmain(int argc, _TCHAR* argv[])
{
video_encode_example("adi.avi");
return 0;
}
vide_encode_example is a function from this c item(file/module) i created in the console application project. I have a file called example.c and the video_encode_example is in the example.c
Now i added to the solution a new dll project and the main.cpp file is empty except the line: #include "stdafx.h"
What i want to do in this dll project in the main.cpp is two things:
To create some function for example
void thisstart()
{
}
Then i want to in this start function to call a start() function which is in a c file/module i created in the dll project.
So it should look like:
void thisstart()
{
start();
}
Where start(); is from the c module/file
Then i'm going to use this dll in c# and in c# i want to be able to use the thisstart() function.
EDIT
This is the main.h content:
namespace dllproj{
extern "C" void start();
void thisstart();
}
I'm getting and two errors now on dllproj:
Error 2 error C2054: expected '(' to follow 'namespace'
4 IntelliSense: expected an identifier
Then this is the cpp file content now:
#define dllproj;
#include "stdafx.h"
#include "targetver.h"
#include "main.h"
void thisstart()
{
dllproj;::start();
}
And i'm getting two errors:
on the define line: Error 1 error C2008: ';' : unexpected in macro definition
on the dllproj;::start(); Error 3 error C2143: syntax error : missing ';' before ':'
Please show me the complete solution and explain to me also which variable later in CSHARP i will use with the dll to make an instance for it and to call this function/s in the cpp ?
In csharp for example when i add the dll : test = new something(); then test.thisstart();
From the comments "start() is in the dll project in a (c language file i create test.c)"
1) create a header file e.g main.h and add the following
namespace dllproj{
extern "c"
{
extern void start();
}
void thisstart();
}
2)add main.h to main.cpp and define thisstart()
void dllproj::thisstart()
{
dllproj::start();
}
make sure start() is declared with __declspec(dllexport) in the dll.

Categories