I'm trying to implement a simple .dll to my Project which will be builded for the HoloLens Augmented Reality Application. I am trying to simply call a function from my C++ .dll to implement an OpenCV Code but on the HoloLens it throws an error shown below.
.dll C++ Code:
extern "C" void __declspec(dllexport) __stdcall test() {
return;
}
Unity C# Code:
internal class OpenCV
{
// Define the functions which can be called from the .dll.
[DllImport("Project1")]
internal static extern void test();
public static void testmeth()
{
test();
}
}
Error when Debugging on HoloLens with Visual Studio:
System.DllNotFoundException: 'Unable to load DLL 'Project1': The specified module could not be found. (Exception from HRESULT: 0x8007007E)'
Here you can see the Settings and Path of the dll:
Problem:
The source files of OpenCV which I compiled for x86 and used successfully for my UWP App somehow didn't work for the HoloLens.
Solved:
I used the NuGet-Package "OpenCV-HoloLens" for my C++ .dll and copied the .dlls to Unity as well.
Related
I am creating a Windows 10 application that works with files. For the GUI I am using UWP (C#) and for the file processing I want to use the C language (Visual Studio 2019).
I have tried these solutions (none of them worked):
C program created with Windows Desktop Wizard (DLL), then DllImport
Tried to add it to the UWP by using DllImport (which in a C# Console App program worked).
The code in the C file:
#include<stdio.h>
_declspec(dllexport) int getNumberOfFiles()
{
...
}
The code in the C# UWP app:
[DllImport(#"...\WorkFilesDll\Debug\WorkFilesDll.dll", EntryPoint = "getNumberOfFiles", CallingConvention = CallingConvention.Cdecl)]
internal static extern int getNumberOfFiles();
The following exception is thrown:
System.DllNotFoundException HResult=0x80131524 Message=Unable
to load DLL '...\WorkFilesDll\Debug\WorkFilesDll.dll' or one of its
dependencies: Access is denied. (Exception from HRESULT: 0x80070005
(E_ACCESSDENIED))
C program created with Windows Desktop Wizard (DLL), then add as reference
Tried to add the same dll as reference (References->Add Reference->Browse->Add->OK).
After pressing the OK button, the following message indicates the failure:
A reference to "...\WorkFilesDll\Debug\WorkFilesDll.dll" could not be
added. Please make sure that the file is accessible, and that is a
valid assembly or COM component.
I created other types of projects for the C code (C++, UWP): Dll (Universal Windows), Windows Runtime Component (Universal Windows). The results were the same.
I created other types of projects (C#, UWP): Class Library (Universal Windows), Windows Runtime Component (Universal Windows), in order to add theses projects to the UWP and to add to these projects the dll mentioned above (the C code to be added indirectly to the UWP). The results were the same.
I have found many questions and articles like this, but I didn't see a clear answer or the answers didn't work for me. Some of them are:
https://learn.microsoft.com/en-us/cpp/cppcx/dlls-c-cx?view=msvc-160
https://www.c-sharpcorner.com/forums/how-to-use-cpp-dlls-in-c-sharp-uwp-projects
How to call a function from DLL in UWP?
Can you use C++ DLLs in C# code in a UWP?
https://learn.microsoft.com/en-us/cpp/porting/how-to-use-existing-cpp-code-in-a-universal-windows-platform-app?view=msvc-160
I have also read about static libraries. I have failed in implementing them.
How can I put the C code in UWP (C#)?
Are static libraries the answer to my application?
Which are better for this application: the DLLs or the static libraries? Why?
Thank you!
Please check the following steps:
Create a C# UWP project in a new solution.
Add a C++ DLL(Universal Windows) project(named MyDll1) in the same solution.
Add your C code in the C++ DLL project. For example:
//MyDll1.h
#pragma once
extern "C" _declspec(dllexport) int Sum(int a, int b);
//MyDll1.cpp
#include "pch.h"
#include "MyDll1.h"
int Sum(int a, int b)
{
return a + b;
}
Add a Windows Runtime Component(C++/WinRT) project in the same project.
Right-click on the name of the Windows Runtime Component(C++/WinRT) project, and select option Add > Reference, check your DLL project in Projects tab. Click OK.
There is an auto-generated class Class, you could use the class or add other class(Add > New Item > Code > Midl File(.idl)) as needed. The new class must be generated from a midl file. You could get more information about authoring api referring to the document.
Take Class class as an example. Include the header file of dll in Windows Runtime Component(C++/WinRT) project.
//Class.h
#include "..\MyDll1\MyDll1.h"
There is a sample method named MyProperty shown in Class class. The MyProperty method is added to the Class.idl file and the complier will generate the corresponding methods in Class.h and Class.cpp after you build the project. And you need to go to the locations \RuntimeComponent\ RuntimeComponent \Generated Files\sources\Class.h and Class.cpp in File Explorer and open the .h and .cpp file to copy the generated methods into your code in Visual Studio. You could use MyProperty method to pass values to C# project or add other methods in classes. Refer to the document for more information about how to add new method in idl file.
You could call the Sum(int a, int b) of MyDll1 project in MyProperty method.
int32_t Class::MyProperty()
{
int t = Sum(1, 2);
return t;
}
Right-click on the name of the C# UWP project, and select option Add > Reference, check your Windows Runtime Component(C++/WinRT) project in Projects. Click OK.
Add include statement in C# UWP project.
using RuntimeComponent; // RuntimeComponent is the name of Windows Runtime Component(C++/WinRT) project.
You could call the MyProperty method in C# UWP project.
RuntimeComponent.Class myClass = new Class();
var value = myClass.MyProperty;
I have code written in ANSI C that I would like to use in C#. I have compiled the C code into a DLL and created C# wrapper classes to interop with the C code. The point of the wrapper is to simplify a users interaction with the underlying C code.
[DllImport(DLL, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
private static extern void PrintHelloWorld();
public void PrintHelloWorldC()
{
PrintHelloWorld();
}
Above is a simplified example of what I have done so far. Now, I am trying to create a DLL from the C# wrapper classes I wrote. From here I could give both the DLLs created and someone would be able to interact with the C# based DLL to interact with the underlying C based DLL. Below is what I have done and what problem I am having.
I compile the C code into a DLL in Visual Studio 2019 with my Configuration=Release and Platform=Win32.
I compile my C# classes into a DLL in Visual Studio 2019 with my
Configuration=Release, Platform=Win32, and Platform Target as x86.
I create a new project and link my C# DLL and set Platform Target as x86.
I put my C DLL into the Debug folder of the project so that it is available to the C# DLL through the marshal directive.
I try to make a call into the C# DLL and below are the chain of events occurring.
Program calls C# DLL method PrintHelloWorldC() and is successful
Within PrintHelloWorldC() it tries to make a call to PrintHelloWorld();.
Following Error Occurs:
System.BadImageFormatException
HResult=0x8007000B
Message=An attempt was made to load a program with an incorrect format. (Exception from HRESULT: 0x8007000B)
My research yielded that it was most likely a mismatch in Platform Target between the DLLs and Test Project, however, I have double checked all the configurations and they should all be compiled for x86.
Below is what additional testing I have done.
Created a C# Project, and wrote simple code to make a call directly into the C based DLL. This works fine.
It seems that as soon as I try to use the two DLLs on top of each other in another project I start facing issues.
Any help or guidance is appreciated. Thanks in advance!
Update
I have now run through the tutorial 3 times with the same results (Visual Studio/Windows is unable to recognise the DLL as a valid file). This must be an issue with my environment, as mike below ran through the tutorial and it worked fine.
I did notice this in the C++ project's solution explorer on my last run:
Does anyone know if this is okay? There seems to be a lot of Red stop-signs which to me would suggest something bad...
Following this tutorial, I have ended up with the following:
C#
using System.Runtime.InteropServices;
namespace TestImport
{
class Program
{
[DllImport("TestLib.dll")]
public static extern void DisplayHelloFromDLL();
static void Main(string[] args)
{
DisplayHelloFromDLL();
}
}
}
C++
In .cpp file Source Files
#include <stdio.h>
extern "C"
{
__declspec(dllexport) void DisplayHelloFromDLL()
{
printf("Hello from DLL !\n");
}
}
When debugging in Visual Studio:
An unhandled exception of type 'System.DllNotFoundException' occurred in TestImport.exe
Additional information: An attempt was made to load a program with an incorrect format. (Exception from HRESULT: 0x8007000B)
When running the built EXE (from he same folder as the Dll):
An attempt was made to load a program with an incorrect format.
Have I done anything wrong in the above code?
I did do all of this in VS 2015, where the tutorial calls for VS 2010, howeve rI couldn't find a more up-to-date tutorial.
When I try to add the project as a reference by Project -> Add Reference ... I am seeing this error:
A reference to 'Path\To\MyLib.dll' could not be added. Please make sure
that the file is accessible, and that it is a valid assembly or COM
component.
Which makes me think that the issue is either with the source code or the DLLs configuration.
I have also tried building both files and putting them in the same folder before running the Executable, but without any improved results (same error as when running the EXE above).
Solution Explorer Screenshot:
Make sure the name of your C++ project and DllImport parameter are the same. Also, if the dll file is not located in the same directory as your C# project, make sure to add the dll into your Debug/Release folder.
Also! Make sure that you are running in the same 32/64 bit mode when compiling.. if you compiled the dll using 32 bit and try to use it in a 64 bit C# program, it won't work.
OK, now build this application, and then copy the previously built DLL into the Debug/Release directory of the current application. The DLL should be in the same directory as your main application.
Did you do the bolded text? Your C# app won't know where to look for the DLL and it looks in the build folder, by default.
An unhandled exception of type 'System.DllNotFoundException'
It happened to me, because of the imported c++ dll, its own dependency dlls were missing.
After copying them into Debug/Release folder everything worked.
I wrote a C++ Class Library in Visual Studio that just defines a function that invokes some Python:
#pragma once
#include <Python.h>
extern "C"
__declspec(dllexport)
void python()
{
Py_Initialize();
PyRun_SimpleString("2 + 2");
}
I made another project in the same solution that was a C# Blank Universal app. I tried to reference the DLL generated from the previous project I mentioned:
using System;
...
namespace StartupApp
{
...
sealed partial class App : Application
{
private const string CPPPythonInterfaceDLL = #"pathtodll";
[DllImport(CPPPythonInterfaceDLL, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
private static extern void python();
public static void Python()
{
python();
}
...
public App()
{
...
Python();
}
...
}
}
The app is in a Release configuration.
Whenever I try to run the app on my Local Machine, it always gives an error:
The program '[2272] StartupApp.exe' has exited with code -1073741790 (0xc0000022).
Activation of the Windows Store app 'ab6a8ef2-1fa8-4cc7-b7b3-fb7420af7dc3_7dk3a6v9mg4g6!App' failed with error 'The app didn't start'.
So my question is this: can I reference a C++ class library from a C# UWP project? Or does the security on UWP apps not allow this?
Or is it because of Python.h?
EDIT:
I built the project with a DLL project and a Runtime Component that wrapped it, and now I have this error:
An exception of type 'System
'System.DllNotFoundException' occurred in StartupApp.exe but was not handled in user code
Additional information: Unable to load DLL 'pathtodll': Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))
I added a user to the DLL with the object name "Everyone" (I am not sure how else to give everyone permissions) but the error still comes up.
Firstly, UWP can't consume a legacy C++ dll just by DLLImport.
If you want to expose legacy c++ functions to C#, the first suggestion is to wrap that C++ logic using a WinRT component. Then you can reference this component in UWP application by following steps: adding it to the project, open the files' properties in the Solution Explorer window, and mark them as content to be included in the app package. This post would be helpful. This one provides more detailed steps.
If you want to PInvoke the dll, you can follow these steps (You can refer to this MSDN post):
Add win32 dll into your UWP project making sure to set its type as 'content'
Then in the proper cs file, using DllImport to PInvoke the dll.
There is one more thing: You need to make sure your Python dll is not using prohibited APIs in WinRT. You can check this by using /ZW compile option for the dll.
I am trying to create a managed wrapper around a C++ dll. When I try to run a test app, I get an error saying loading the dll failed. This turns out to be a problem with trying to find the CRT. Copying the CRT to the same directory moves past this problem, but then throws an error saying the application loaded the C Runtime incorrectly (R6034). A native C++ program has no trouble with either of these issues.
The dll was compiled with vc 2008 - the managed code is compiled in 2010.
The dll has a manifest and I have tried copying the exact version of the CRT into the working directory with the same result as above.
My questions are :
Why can the native program load the CRT, but the managed wrapper can't find it?
Where could I look for things to try to fix the second error about loading the CRT?
Could this be because of name mangling, CallingConvention, etc?
C++ Code (I only have the header):
class Foo {
public:
static void startCall(std::string hostname);
}
C# Code:
[DllImport("mydll.dll")]
public static extern void startCall(string hostname );
public Test()
{
string hostname = "";
startCall(hostname);
}
As far as I know it is impossible to have STL in function interfaces if you want to use the functions in C#.
If you can change the C++ library interface, change it to use char* instead of strings. If you can't write a proxy library which exposes the interface with char* and converts it to std::string and then calls the c++ library which has functions with std::string