Unamanaged call is not happening from the managed C# code - c#

I am calling unamanaged function from the managed code. But Unamanaged call is not happening.
Managed C# code:
(Created a project (Sampletest) from Visual C# -> Console App)
Sampletest:
namespace Sampletest
{
class Program
{
const string Dllpath2 = #"C:\Users\Sampletest\SampleDll\Debug\SampleDll.dll";
[DllImport(Dllpath2, EntryPoint = #"IsTherePower", CallingConvention = CallingConvention.Cdecl)]
public static extern Boolean IsTherePower();
static void Main(string[] args)
{
var test = IsTherePower();
Console.ReadKey();
}
}
}
Unmanaged C++ code:
(Created a dll project (SampleDll) from Visual C++ -> Windows Desktop -> Dynamic Link Library)
"IsTherePower()" definition is there in SampleDll.cpp
#include "stdafx.h"
BOOL IsTherePower()
{
BOOL bRetValue = FALSE;
return bRetValue;
}
But when we are making unmanaged call, first it is going to dllmain.cpp file present in unmanaged code.
#include "stdafx.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;
}
then it is not going to
BOOL IsTherePower() function
and comming back to the managed call at "var test = IsTherePower();"
showing the error "Unhandled exception at 0x7705D6C7 (ntdll.dll) in Sampletest.exe: 0xC0000096: Privileged instruction.
Settings i Made:
For C# project,
Debug-> Selected "Enable native code debugging"
And I selected "Debug", "x86"
Please help me to resolve this issue.

You have to declare IsUPSPresent using the __declspec(dllexport) attribute or use a .def-file. Also, to overcome C++ name mangling, your definition has to be extern "C" in C++-code.
extern "C" {
BOOL __declspec(dllexport) IsUPSPresent()
{
BOOL bRetValue = FALSE;
return bRetValue;
}
}

Related

BadImageFormatException: Attempting to use a C++ DLL file in C#?

Win32 C++ DLL project is saved in my bin/Debug file with the other DLLs.
Running Debug x86 mode on my C# project.
From previous attempts to solve this problem I have changed the Build Configuration to x86 from x64 but I still receive the same error.
namespace ComputerToArduino
{
public partial class Form1 : Form
{
[DllImport("MySimpleLib.dll", CharSet = CharSet.Unicode)]
public static extern int AddNumber(int a, int b);
public Form1()
{
InitializeComponent();
disableControlsArduino();
disableControlsMotor();
getAvailableComPorts();
chartInit();
int result = AddNumber(1, 2);
Console.Write(result);
}
}
}
I created a DLL project in Visual studio. This is my main DLL code:
// dllmain.cpp : Defines the entry point for the DLL application.
#include "pch.h"
extern "C" __declspec(dllexport) int AddNumber(int n1, int n2);
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;
}
int AddNumber(int n1, int n2)
{
return n1 + n2;
}
I am receiving this error message which I do not understand:
Exception thrown: 'System.BadImageFormatException' in ComputerToArduino.exe
An unhandled exception of type 'System.BadImageFormatException' occurred in ComputerToArduino.exe
An attempt was made to load a program with an incorrect format. (Exception from HRESULT: 0x8007000B)
'ComputerToArduino.exe' (CLR v4.0.30319: ComputerToArduino.exe): Loaded 'C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\IDE\Remote Debugger\x64\Runtime\Microsoft.VisualStudio.Debugger.Runtime.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
The program '[14748] ComputerToArduino.exe' has exited with code -1 (0xffffffff).
Error after adding extern to C++ function:
Managed Debugging Assistant 'PInvokeStackImbalance' : 'A call to PInvoke function 'ComputerToArduino!ComputerToArduino.Form1::AddNumber' has unbalanced the stack. This is likely because the managed PInvoke signature does not match the unmanaged target signature. Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature.'
In x86 (in contrast to x64), there are different calling conventions. The language C (and extern "C" in C++) defaults to the cdecl calling convention, whereas C# defaults to the stdcall calling convention. Therefore, you must set the calling convention to cdecl in C#, like this:
[DllImport("MySimpleLib.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
public static extern int AddNumber(int a, int b);

passing a very large string as byte array from C++ to C# with Dllimport

I have a very large string in my c++ dll file , I need to pass it to C# as a byte array and I have no idea how to do that !
I know I can use this function in C# :
string result = System.Text.Encoding.UTF8.GetString(bytearray);
My large string is a std::string in C++
I need to know how can I convert my string to A utf8 array and send it to C# and how to get string back in C# application :)
More about the question:
I don't know how to pars byte arrays from C++ to C# like swprintf to StringBuilder .
Here's an example code for my question :
C++ Code:
#include "stdafx.h"
#include <iostream>
#include <cstdio>
#include <fstream>
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;
}
extern "C" __declspec(dllexport) void __stdcall sendasbyte(char* byte_to_send)
{
std::ifstream file_t("testfile.txt");
std::string Read_test_file((std::istreambuf_iterator<char>(file_t)),
std::istreambuf_iterator<char>());
///// NEED TO SEND Read_test_file as byte array to C# HERE :
// <-------- CODE AREA --------->
}
Here's C# Code :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
namespace minimal_project_testapp
{
class Program
{
[DllImport("minimal_project_test.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode)]
private static extern void sendasbyte(byte[] get_String_Byte);
private static byte[] data_from_cpp;
static void Main(string[] args)
{
sendasbyte(data_from_cpp);
string result = System.Text.Encoding.UTF8.GetString(data_from_cpp);
Console.WriteLine(result);
Console.ReadLine();
}
}
}
And the testfile.txt : https://textuploader.com/dvvbb
Here's how to Do That clear and perfectly :D
1 > Change your c++ function to this :
extern "C" __declspec(dllexport) char* __stdcall test_int()
{
std::ifstream file_t("testfile.txt");
std::string Read_test_file((std::istreambuf_iterator<char>(file_t)),
std::istreambuf_iterator<char>());
int size_of_st = Read_test_file.length();
std::string test1 = std::to_string(size_of_st);
char* cstr = new char [size_of_st];
std::strcpy(cstr, Read_test_file.c_str());
return cstr;
}
2 > Don't forgot to add #define _CRT_SECURE_NO_WARNINGS
3 > Add Dllimport to your C# application
[DllImport("minimal_project_test.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode)]
private static extern IntPtr test_int();
4 > And finally use it everywhere you need like this :
IntPtr _test_from_Cpp = test_int();
int _test_char_count = <Enter Length of your string>;
byte[] _out_char_value = new byte[_test_char_count];
Marshal.Copy(_test_from_Cpp, _out_char_value, 0, _test_char_count);
string final_string = System.Text.Encoding.UTF8.GetString(_out_char_value);
Boom! it Works !!! ;)

Getting AccessViolationException while Assigning Delegate from C# to FunctionPointer in NativeCode

From C# code I'm trying to call a API from a *.c file. But I'm getting AccessViolationException.
Earlier I was getting BadImageFormatException, but I solved it by putting both the exe and the dll together in one location.
I suspect that it has something to do with CallingConvention of Cdecl or StdCall or with PlatformType=x86 or x64.
In My C#. exe I've set the CPU to x86 and in my NativeCode.dll the calling convention is mentioned as Cdecl only.
I'm not able to understand that how to solve this issue,there are many posts on web explaining about this problem but somehow I'm not able to find any concrete solution to this issue.
In case of any more details please let me know.
Below mentioned is some code from files which can highlight the problem:
Header.H file
typedef int BOOL;
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
typedef BOOL REGFUNCTION( char *pRegKey, char *pBuffer, int iBufSize );
Implementation.c file
#ifdef SWSCANCODE_EXPORTS
#define SWSCANCODE_API __declspec(dllexport)
#else
#define SWSCANCODE_API __declspec(dllimport)
#endif
#ifdef SWSCAN_APIS
SWSCANCODE_API BOOL SWSetGetRegKeyValue ( REGFUNCTION* pGetRegKeyValue );
#endif
SWGLOBALS* pSWGlobals;
SWSCANCODE_API BOOL SWSetGetRegKeyValue( REGFUNCTION * pGetRegKeyValue )
{
BOOL bInitStatus; // initialization status
bInitStatus = TRUE; // assume initialization will be successful
pSWGlobals->pGetRegKeyValue = pGetRegKeyValue;
if(NULL!=pSWGlobals->pGetRegKeyValue)
{
printf("I don't know");
}
return( bInitStatus );
}
C# code
class Program
{
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate int REGFUNCTION([MarshalAs(UnmanagedType.LPStr)]string pRegKey, [MarshalAs(UnmanagedType.LPStr)]string pBuffer, int iBufSize);
[DllImport("NativeCode.dll", EntryPoint = "SWSetGetRegKeyValue", CallingConvention = CallingConvention.Cdecl)]
[return:MarshalAsAttribute(UnmanagedType.Bool)]
public static extern Boolean SWSetGetRegKeyValue(IntPtr pGetRegKeyValue);
static void Main(string[] args)
{
REGFUNCTION dele = GetRegKeyValue;
IntPtr ptr = Marshal.GetFunctionPointerForDelegate(dele);
GC.KeepAlive(dele);
bool bSetRegKeyValueOk = SWSetGetRegKeyValue(ptr);
}
public static int GetRegKeyValue(string pRegKey, string pBuffer, int iBufSize)
{
Console.WriteLine("Successful in calling the method");
return 0;
}
}

How to call WIN32 DLL in C# project - EntryPointNotFoundException

I have created a WIN32 DLL project and its dllmain.cpp is as follows;
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;
}
_declspec(dllexport) float RGBCompare()
{
return 100;
}
My target is to call method RGBCompare from a C# project and as per rule I have mentioned dllexport tag before it.
On the other side in C# project I have defined an entry point as follows;
namespace LogoFinderWrapper
{
public class LogoFinder
{
[DllImport("LogoIdentifier.dll", EntryPoint = "RGBCompare")]
private static extern float Api_RGBCompare();
public static float RGBCompare()
{
return Api_RGBCompare();
}
}
}
When I call DLL it raises exception System.EntryPointNotFoundException.
Please could any one help me in this regard?
Your native code is C++ and the name is mangled before export. Possible solutions:
Use the mangled name in the EntryPoint parameter. Find out the mangled name with dumpbin or Dependency Viewer.
Use a .def file rather than __declspec(dllexport) to control which functions are exported.
Suppress mangling with extern "C" in your C++ source code.
The final option would look like this:
extern "C"
{
__declspec(dllexport) float RGBCompare()
{
return 100;
}
}

attempted to read or write protected memory - dllimport

I'm having a problem trying to import a c++ dll into c#
I always get the error "attempted to read or write protected memory" when I call the constructor of the dll class. I've been locking in other solutions for the same answer but I couldn't found solution.
I decided to use a simple function to discard that the error came from the c++ part but I'm having the same problem...
Here is my code:
main.cpp:
#include "main.h"
simple_dll::simple_dll(int num) : numero(num) {}
int simple_dll::getNumero() {
return this->numero;
}
extern "C" DLL_EXPORT BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
// attach to process
// return FALSE to fail DLL load
break;
case DLL_PROCESS_DETACH:
// detach from process
break;
case DLL_THREAD_ATTACH:
// attach to thread
break;
case DLL_THREAD_DETACH:
// detach from thread
break;
}
return TRUE; // succesful
}
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);
class DLL_EXPORT simple_dll {
public:
DLL_EXPORT simple_dll(int num);
DLL_EXPORT int getNumero();
int numero;
};
#ifdef __cplusplus
}
#endif
#endif // __MAIN_H__
And the C# code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Reflection;
namespace prueba_dll_VS
{
unsafe class Program
{
[System.Runtime.InteropServices.DllImport("simple_dll.dll", EntryPoint = "_ZN10simple_dllC2Ei")]
private static extern System.IntPtr simple_dll(int num);
[System.Runtime.InteropServices.DllImport("simple_dll.dll", EntryPoint = "_ZN10simple_dll9getNumeroEv")]
private static extern int getNumero(System.IntPtr hObject);
static void Main(string[] args)
{
System.IntPtr ptr_simple_dll = simple_dll(4); //HERE IS WHERE THE ERROR RAISES
int hora = getNumero(ptr_simple_dll);
Console.WriteLine(hora);
Console.ReadLine();
}
}
}
I'm getting mad, this can't be so difficult.
Thanks in advance.
The problem is the calling convention. In the current form, the functions are exported in thiscall, but the DllImport attribute defaults to stdcall (or cdecl on smartphones).

Categories

Resources