Now I have a Unity (C#) project, which calls my C++ project from a dll. They both worked fine, so as calling C++ functions from Unity.
However, when I try add one line to call a function another library (NLOpt library, from another dll) in the C++ project, the generated dll becomes unable to be loaded in the Unity project.
Plugin.h
extern "C" __declspec(dllexport) bool __stdcall LoadData(int agent_num, int frame_num, float* data);
Plugin.cpp
#include "Plugin.h"
#include <nlopt.h>
__declspec(dllexport) bool __stdcall LoadData(int agent_num, int frame_num, float* d)
{
...
nlopt_opt opt = nlopt_create(NLOPT_LN_COBYLA, 3); //this line
}
As I add the line above, Unity will the following error:
Plugins: Failed to load 'Assets/Plugins/BirdOpti/BirdOpti.dll'
and
DllNotFoundException: Opti
I have tried couple of times so I am sure the problem is the line.
Did I do anything wrong?
Adding also the used dll file to the plugin directory solves the problem.
Related
Hy everyone i have a bit of a problem, I program mostly in python, and it's been a while actually since i coded in C# and i code in mql every now and again. My problem is i built a C# dll file that has a couple of simple functions:
[DllExport("debugger", CallingConvention = CallingConvention.StdCall)]
[return: MarshalAs(UnmanagedType.LPWStr)]
public static string debugger()
{
return "Send help!! SOS";
}
[DllExport("debugger2", CallingConvention = CallingConvention.StdCall)]
public static int debugger2()
{
return 12345;
}
This is my simple code from my C# file, it's all inside a public static class and the Solution platform is x64. Code compiles just fine and i find no issues. Now this is how my MetaEditor code looks:
#import "simpleFunctions.dll"
string debugger();
int debugger2();
#import
int OnInit()
{
//Print a statement just to show where code crashes
Print("We are definitly in it :D");
Print(debugger);
}
From what the Journal tells me everything runs just fine, the file is added from libraries and the print statement at the beginning of the OnInit function runs as well. The problem is come when calling the first debugger function from my dll file, just below my Print statement in the journal i get the following errors:
- Cannot find 'debugger', in 'simpleFunctions.dll'
- unresolved import function call
- OnInit critical error
- tester stopped because OnInit failed
I have searched all over the internet to my dissatisfaction of finding that no one really answers this question in a practical way. I suspect the error lies maybe in the C# side of things with regard to data type differences but i really don't know where to continue looking at this point. Any help would be greatly appreciated.
Well after searching probably every website for an answer relating to my question, switching back to python and trying a different way to connect to mql5 (using sockets), than finally trying C++ and spending the last two days learning that, I think I finally solved my problem. Only posting this to help anyone who might have a similar problem in the future. I figured that since MQL5 is more like C++ than C# the linking process would be a bit easier. The code it's self was not complex at all because I was just trying to get functions running in MQL5 from C++.
#include "pch.h"
#include "CPPMQLSQLConnector.h"
#define CPPMQLSQLCONNECTOR_API
#include <string>
std::string __stdcall myString(std::string Words)
{
static std::string myWords = "This is about to work I can feel it. ";
return myWords + Words;
}
int __stdcall myInt(int numbr)
{
static int myNumber = 1998;
numbr = 22;
return myNumber + numbr;
}
Note the __stdcall before method pointer, calling convention is required to let MQL5 know how to get the functions from the library.
In my C++ header file I let C++ know which functions I want to export using the '__declspec(dllexport)' and the '__declspec(dllimport)', my opinion on this issue is worth as much as you paid for it but my understanding is that the export keyword let's C++ know which functions I would like to export and the import keyword is used by MQL5 or which ever application, to know which functions to import. My header file
#pragma once
#include <string>
#ifndef MYDLL
#define MYDLL
#ifdef CPPMQLSQLCONNECTOR_API
extern "C" __declspec(dllexport) std::string __stdcall myString(std::string Words);
extern "C" __declspec(dllexport) int __stdcall myInt(int numbr);
#else
extern "C" __declspec(dllimport) std::string __stdcall myString(std::string Words);
extern "C" __declspec(dllimport) int __stdcall myInt(int numbr);
#endif
#endif
We use the extern "C" keyword to let the compiler know it should expect 'C' code.
Finally the MQL5 code, it's very simple. We just import the dll and and start using the functions for what ever purpose they were made
#import "CPPMQLSQLConnector.dll"
string myString(string s);
int myInt(int i);
#import
int OnInit()
{
string Word = "Momma I made it!!!!!!!!!!!!";
int numbr = 25;
Print("We definitely init ;D");
Print("La string: ", myString(Word));
Print("La integer: ", myInt(numbr));
return(INIT_SUCCEEDED);
}
I am trying to follow tutorial calling code from C++ into C#.
I followed the coding part correctly.
But when I run the code I get exception:
System.DllNotFoundException: 'Unable to load DLL 'SampleNativeLib': The specified module could not be found. (Exception from HRESULT: 0x8007007E)'
I create C# library as simple application file.
And C++ as dynamic .dll.
In the original tutorial (I also have full project file of it) in the C# project in the references there are no references to C++ .dll.
I would like to ask how C++ is referenced to C#?
The code of C#
using System;
using System.Linq;
using System.Runtime.InteropServices;
namespace ObjectPinning {
class Program {
[DllImport("SampleNativeLib")]
static extern int SetData([MarshalAs(UnmanagedType.LPArray)] int[] darray);
[DllImport("SampleNativeLib")]
static extern int DoCalc();
static void Main(string[] args) {
var data = Enumerable.Range(0, 10).Select(i => i + 1).ToArray();
GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);
Console.WriteLine(SetData(data));
Console.WriteLine(DoCalc());
Console.ReadLine();
GC.Collect();//Clean up any garbage object
Console.WriteLine(DoCalc());
handle.Free();
}
}
}
The code of C++:
// SampleNativeLib.cpp : Defines the exported functions for the DLL application.
//
#include "stdafx.h"
int* g_pData;
extern "C" __declspec(dllexport) int WINAPI DoCalc() {
int sum = 0;
for(int i = 0; i < 10; i++)
sum += g_pData[i];
return sum;
}
extern "C" __declspec(dllexport) int WINAPI SetData(int* data) {
g_pData = data;
return DoCalc();
}
My project file:
Download
Teachers File:
Download
My file
Teacher File
The exception you get is most likely because you didn't add the dll to the C# executable path. In the first step the application searching the dependencies in the exe directory, if not found, then it goes through the Window environment variables. That is why we don't need to copy the dlls when we use some of the Windows API function, because if you look at at your PATH variable, you'll have %SystemRoot% variable which links to your windows folder.
In C# you can't really reference C++ projects as you already know when adding another C# project, since you calling from managed code to unmanaged/native code.
Important note when you building your own C++ dll, make sure the compiler environment set to x32 bit, otherwise you'll get some other exceptions when calling C++ code from C#.
What actually expose the C++ function to allow for it consumed by other languages, is the:
extern "C" __declspec(dllexport)
On the signature of the function. So that gives you the power to do almost everything you can do with C++ also in C#/Java.
I have compiled a native dll for windows mobile SDK, and then created c# project to call it from. However, all i get is a MissigMethodException.
Dll is in the same folder as Managed executable file.
Here is how exported functions look in header:
namespace cuttingStream
{
/**
* Открывается файл и производится его проверка.
**/
__declspec(dllexport) bool open_png_file(char* , pngDataStructures* );
__declspec(dllexport) void close_png_file(pngDataStructures*);
...
}
Here is how i import them:
static class CuttingStreamWrapper
{
[DllImport("libpngStreamWrap.dll", EntryPoint = "open_png_file")]
public static extern bool OpenPngFile(string fileName, out pngDataStructures dataStruct);
[DllImport("libpngStreamWrap.dll", EntryPoint = "close_png_file")]
public static extern bool ClosePngFile(ref pngDataStructures dataStruct);
}
Here is dumpbin's output (relevant part):
1 0 00001340 ?close_png_file#cuttingStream##YAXPAUpngDataStructures###Z
2 1 00001194 ?open_png_file#cuttingStream##YA_NPADPAUpngDataStructures###Z
After marking functions with extern "C" in both source file and header, dumpbin output changed to:
ordinal hint RVA name
1 0 00001314 close_png_file
2 1 0000118C open_png_file
Which seems to be not mangled.
However, the problem remains. Here is the exception i recieve:
System.MissingMethodException was unhandled
Message="Не удается найти PInvoke DLL \"libpngStreamWrap.dll\"."
StackTrace only has the main function of a program, where i try to call wrapped function.
Update:
After running dependency walker on the dll i am trying to load, i've got 2 dependencies: Coredll.dll, msvcr90d.dll. On the device i am trying to deploy to ther is only msvcr80.dll. That explains the failure to load.
The issue was rooted in the dll's dependency on msvcr90d.dll, that is not found on the device. Once dependency was eliminated (by switching to /MTd from /MDd), dll was found.
Is it possible to invoke a g++ executable file's function from mono in Ubuntu? Note that both C++ and C# code compiled in Ubuntu Operation System.
C++ application source:
#include <stdlib.h>
static int32_t Sum(int32_t a, int32_t b){
return a + b;
}
/*
*
*/
int main(int argc, char** argv) {
return (EXIT_SUCCESS);
}
C# mono application source:
using System;
using System.Runtime.InteropServices;
namespace MonoCsTest
{
class MainClass
{
[DllImport("/home/.../MonoCsTest/bin/Debug/testcpp")]
public static extern Int32 Sum(Int32 a, Int32 b);
public static void Main (string[] args)
{
Console.WriteLine (" 5 + 6 = " + Sum(5,6));
}
}
}
This throws DllNotFoundException
You need to compile the library as a shared library: a static library can't be loaded at runtime with P/Invoke.
The fact that you added a main() function suggests that you're compiling the code into an executable instead.
So the first thing for you is to learn how to compile a shared library, you can try something like:
gcc -shared -o libtestcpp.so testcpp.cpp
Then change the DllImport name to the path to the complete library name:
DllImport("/home/yourlogin/MonoCsTest/bin/Debug/libtestcpp.so")
The other mistake you made is not considering the C++ manadated name mangling: the simpler solution here is to export Sum() as a C function surrounding it with extern "C" {}.
To diagnose such mistakes it is often useful to enable the debug logging from mono using:
MONO_LOG_LEVEL="debug" MONO_LOG_MASK="dll" mono yourprog.exe
As long as a symbol is exported and Mono can understand the parameters (enough to marshal data to/from them), then yes, you can do this. I think the Mono pages on PInvoke actually mention that you can invoke functions exported by both libraries and executables, including an executable that embeds Mono.
You need to verify that the symbol is indeed being exported, and more importantly, that it is not mangled or you match that in the C# side. That's the spot I've had the most stupid problems with.
I am working on a project that requires some image processing. The front end of the program is C# (cause the guys thought it is a lot simpler to make the UI in it). However, as the image processing part needs a lot of CPU juice I am making this part in C++.
The idea is to link it to the C# project and just call a function from a DLL to make the image processing part and allow to the C# environment to process the data afterwards. Now the only problem is that it seems I am not able to make the DLL. Simply put the compiler refuses to put any function into the DLL that I compile.
Because the project requires some development time testing I have created two projects into a C++ solution. One is for the Dll and another console application. The console project holds all the files and I just include the corresponding header into my DLL project file. I thought the compiler should take out the functions that I marked as to be exported and make the DLL from them. Nevertheless this does not happens.
Here it is how I defined the function in the header:
extern "C" __declspec(dllexport) void _stdcall RobotData(BYTE* buf, int** pToNewBackgroundImage, int* pToBackgroundImage, bool InitFlag, ObjectInformation* robot1, ObjectInformation* robot2, ObjectInformation* robot3, ObjectInformation* robot4, ObjectInformation* puck);
extern "C" __declspec(dllexport) CvPoint _stdcall RefPointFinder(IplImage* imgInput, CvRect &imgROI,
CvScalar &refHSVColorLow, CvScalar &refHSVColorHi );
Followed by the implementation in the cpp file:
extern "C" __declspec(dllexport) CvPoint _stdcall RefPointFinder(IplImage* imgInput, CvRect &imgROI,&refHSVColorLow, CvScalar &refHSVColorHi ) { \\...
return cvPoint((int)( M10/M00) + imgROI.x, (int)( M01/M00 ) + imgROI.y) ;}
extern "C" __declspec(dllexport) void _stdcall RobotData(BYTE* buf, int** pToNewBackgroundImage, int* pToBackgroundImage, bool InitFlag, ObjectInformation* robot1, ObjectInformation* robot2, ObjectInformation* robot3, ObjectInformation* robot4, ObjectInformation* puck) { \\ ...};
And my main file for the DLL project looks like:
#ifdef _MANAGED
#pragma managed(push, off)
#endif
/// <summary> Include files. </summary>
#include "..\ImageProcessingDebug\ImageProcessingTest.h"
#include "..\ImageProcessingDebug\ImageProcessing.h"
BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
return TRUE;
}
#ifdef _MANAGED
#pragma managed(pop)
#endif
Needless to say it does not work. A quick look with DLL export viewer 1.36 reveals that no function is inside the library. I don't get it. What I am doing wrong ?
As side not I am using the C++ objects (and here it is the C++ DLL part) such as the vector. However, only for internal usage. These will not appear in the headers of either function as you can observe from the previous code snippets.
Any ideas? Thx,
Bernat
It seems you are confused about which files to include in your DLL project vs your console project. If it is true that "The console project holds all the files" then this is your problem.
Your DLL project needs to include the cpp file which has the __declspec(dllexport)s. As you describe it, you have included your RefPointFinder() & RobotData() functions in the console project. In other words your DLL has no functions in it whatsoever, regardless of whether anything is exported.
Just including the .h files in the DLL main file does nothing by itself. It doesn't include these functions in the DLL.