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);
}
Related
This question already has answers here:
Unable to find an entry point when calling C++ dll in C#
(3 answers)
Closed 3 years ago.
I created a C++ (native) DLL that exports one function and I'm trying to call in from C# (managed) code and I receive runtime error that the function name can't be found in my DLL.
Here's the code of the DLL:
#include "pch.h"
#include "framework.h"
#include "Device.h"
// This is an example of an exported function.
DEVICE_API bool DeviceAvailable(void)
{
return false;
}
The header exports the function like:
#ifdef DEVICE_EXPORTS
#define DEVICE_API __declspec(dllexport)
#else
#define DEVICE_API __declspec(dllimport)
#endif
DEVICE_API bool DeviceAvailable(void);
In C# I import the function as such:
.. enclosing code ...
internal static class NativeMethods
{
[DllImport("Device.dll", CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DeviceAvailable();
[DllImport("user32.dll", CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.I4)]
public static extern int MessageBox(IntPtr hWnd, String text, String caption, uint type);
}
When I call NativeMethods.DeviceAvailable(), I get an error on invocation:
System.EntryPointNotFoundException
HResult=0x80131523
Message=Unable to find an entry point named 'DeviceAvailable' in DLL 'Device.dll'.
The MessageBox function works fine when called by the program (C#). A C++ test program is able to find and invoke the DLL function.
I guess your problem related to access settings on function level when creating the mentioned functions ic DLL.
here
you can find a useful links could help you to understand the case better and to find the best solution.
I am trying to use "libheif" library in my UWP app to decode some HEIC images.
In the heif.h I added the fallowing C++ code extern "C" __declspec(dllexport) to the functions I want to invoke from my C# code:
LIBHEIF_API
extern "C" __declspec(dllexport) struct heif_context* heif_context_alloc(void);
LIBHEIF_API
extern "C" __declspec(dllexport) void heif_context_free(struct heif_context*);
LIBHEIF_API
extern "C" __declspec(dllexport) struct heif_error heif_context_read_from_file(struct heif_context*, const char* filename,
const struct heif_reading_options*);
...
Then i compiled the library into a DLL file and added it to my UWP project. In the C# code I did this:
namespace Libraries
{
public class PInvokeCode
{
[DllImport("ms-appx:///libheif.dll")]
public static extern struct heif_context_alloc();
[DllImport("ms-appx:///libheif.dll")]
public static extern void heif_context_free(struct heif_context);
[DllImport("ms-appx:///libheif.dll")]
public static extern struct heif_error heif_context_read_from_file(struct heif_context*, const char* filename,
const struct heif_reading_options*);
}
}
Of course in my UWP i allowed unsafe code nad i set the DLL as content. still, however, i cant seem to get the code to work. It is my first time attempting such thing and I dont know ecactly where i am going wrong!
If you need it, here are the links to libheif.dll and the heif.h files..
You have to identify the application is running as a 32-bit or 64-bit
application.
Then ensure libheif.dll (main) could be linked to dependency dlls which are locate at the same directory libde265.dll
(decoder) and libx265.dll (encoder).
Thus download from
https://github.com/mcychan/libheif/releases if any
libraries that mentioned above is missing.
I'm trying to use native c++ dll inside a c# application.
I followed this article to get started.
Its working fine while the dll using only c files (like in the tutorial), but when using cpp files I cant make it work.
using the dumpbin tool I can see that my exported function names changed.
for example a function call 'next' changed to '?next##YAHH#Z' and when I'm trying to call it in the c# code it cant find it.
my dll code is:
__declspec(dllexport)
int next(int n)
{
return n + 1;
}
the c# code
[DllImport("lib.dll", CallingConvention = CallingConvention.Cdecl)]
extern static int next(int n);
its the same code while using c file or cpp files
Thanks in advance
Amichai
What you are attempting to do is to make a trampoline function, to externalize the use of your C++ objects.
What you are experiencing is called symbol mangling. It is a c++-specific way of naming the symbols (like the functions) in a dynamic library and an executable, to enable polymorphism.
You have to specify that you want to cancel the mangling effect by using an extern "C" statement in your library code, just like this:
extern "C" __declspec(dllexport)
int next(int n)
{
return n + 1;
}
More on this here: Exporting functions from a DLL with dllexport
Please provide the Entry Point
An example below
[DllImport("lib.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "next", CharSet = CharSet.Ansi)]
static extern int next(int n);
Hopefully It helps.
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.
I have a particular function in an Excel addin(xll).
The addin is proprietary and we do not have access to the source code. However we need to call some functions contained within the addin and we would like to call it from a C# program.
Currently, I was thinking of writing a C++ interface calling the Excel function with xlopers, then calling this C++ interface from C#.
Does anybody who has prior experience of this kind of issues know what would be the best solution for that ?
Anthony
You need to create a fake xlcall32.dll, put it in the same directory as your XLL (do not put excel's own xlcall32.dll in the PATH). Here is some code:
# include <windows.h>
typedef void* LPXLOPER;
extern "C" void __declspec(dllexport) XLCallVer ( ) {}
extern "C" int __declspec(dllexport) Excel4 (int xlfn, LPXLOPER operRes, int count,... ) { return 0; }
extern "C" int __declspec(dllexport) Excel4v(int xlfn, LPXLOPER operRes, int count, LPXLOPER far opers[]) {return 0;}
Now suppose I have an XLL called xll-dll.xll with a function called (use "depends.exe" to find out the names of the exported functions) xlAdd that well adds two doubles:
extern "C" __declspec(dllexport) XLOPER * __cdecl xlAdd(XLOPER* pA, XLOPER* pB);
The following code calls it:
# include <windows.h>
# include <iostream>
// your own header that defines XLOPERs
# include <parser/xll/xloper.hpp>
// pointer to function taking 2 XLOPERS
typedef XLOPER * (__cdecl *xl2args) (XLOPER* , XLOPER* ) ;
void test(){
/// get the XLL address
HINSTANCE h = LoadLibrary("xll-dll.xll");
if (h != NULL){
xl2args myfunc;
/// get my xll-dll.xll function address
myfunc = (xl2args) GetProcAddress(h, "xlAdd");
if (!myfunc) { // handle the error
FreeLibrary(h); }
else { /// build some XLOPERS, call the remote function
XLOPER a,b, *c;
a.xltype = 1; a.val.num = 1. ;
b.xltype = 1; b.val.num = 2. ;
c = (*myfunc)(&a,&b);
std::cout << " call of xll " << c->val.num << std::endl; }
FreeLibrary(h); }
}
int main()
{test();}
My exe actually works (to my own surprise), and output 3 as expected. You must have some knowledge of what your XLL actually expects for parameters. If it allocates some memory, you must check if the #define xlbitDLLFree 0x4000
is set on your XLOPER c->type, and call back "xlAutoFree".
You might like to try XLL Plus http://www.planatechsolutions.com/xllplus/default.htm. It's a bit pricey, but the
XLL Wrapper Libraries feature is exactly what you are looking for:
"Sometimes it is useful to be able to call your Excel add-in functions from other environments, such as command-line programs or interactive applications, written in C++, Java, C# or Visual Basic. The Xll Wrapper toolkit contains tools, a runtime library, samples and documentation to help with the development of COM modules and .NET assemblies that wrap Excel XLL add-ins"
An Excell add-in DLL might be written in C#. If so, then you can probably bypass Excel altogether. Might need a wrapper though.
check whether assembly is available in program files where you install the plguin,
reference that assembly directly to your c# project - check the object browser for your class, method or object
You should be able to use reflection to get access to your addin. try using The Reflector to see what's available.