Suppose I want to call c++ functions from a c# code, I am having the following problem:
Case 1:
class abc
{
private :
int a ;
public :
int getValue()
{
return 100;
}
};
int GetCounter()
{
abc* p = new abc();
int i = p->getValue();
return i;
}
This case when calling the function from C# throws me a DLL not found exception.
Case 2:
int GetCounter()
{
int i = 333;
return i;
}
The case when calling the function from C# works just fine.
Any ideas why? How can I fix it?
use this sample Line of code in CPP Project (MathFuncsDll.h)
extern "C" __declspec(dllexport) double Add(double a, double b);
extern "C" __declspec(dllexport) double Sub(double a, double b);
extern "C" __declspec(dllexport) double Mul(double a, double b);
extern "C" __declspec(dllexport) double Div(double a, double b);
in C# Code use like this
[DllImport("MathFuncs.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern Double Add(Double a, Double b);
[DllImport("MathFuncs.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern Double Mul(Double a, Double b);
[DllImport("MathFuncs.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern Double Sub(Double a, Double b);
[DllImport("MathFuncs.dll",CallingConvention = CallingConvention.Cdecl)]
public static extern Double Div(Double a, Double b);
[DllImport("MathFuncs.dll",CallingConvention = CallingConvention.Cdecl)]
public static extern Double Bat(Double a, Double b);
Related
I've been trying to write a c++ dll that could be ran in c#. In Visual Studio, I've added the '/ZctwoPhase-' command line options and turned off "Debug Information Format" as instructed in this post Howver I still get
1>cl : command line error D8016: '/clr' and '/Za' command-line options are incompatible
How can i solve this?
// c# dll stuff ->
extern "C" _declspec(dllexport) void* Create() {
return (void*) new RPCMapper();
}
extern "C" _declspec(dllexport) bool sharpaSetLLAOffsetsElement(RPCMapper* rpc , int a, double b) {
return rpc->aSetLLAOffsetsElement(a, b);
}
extern "C" _declspec(dllexport) bool sharpaSetLLAScaleFactorsElement(RPCMapper * rpc, int a, double b) {
return rpc->aSetLLAScaleFactorsElement(a, b);
}
extern "C" _declspec(dllexport) bool sharpaSetPixelOffsetsElement(RPCMapper * rpc, int a, int b) {
return rpc->aSetPixelOffsetsElement(a, b);
}
extern "C" _declspec(dllexport) bool sharpaSetPixelScaleFactorsElement(RPCMapper * rpc, int a, int b) {
return rpc->aSetPixelScaleFactorsElement(a, b);
}
extern "C" _declspec(dllexport) bool sharpaSetYNumCoefficientsElement(RPCMapper * rpc, int a, double b) {
return rpc->aSetYNumCoefficientsElement(a, b);
}
extern "C" _declspec(dllexport) bool sharpaSetYDenCoefficientsElement(RPCMapper * rpc, int a, double b) {
return rpc->aSetYDenCoefficientsElement(a, b);
}
extern "C" _declspec(dllexport) bool sharpaSetXNumCoefficientsElement(RPCMapper * rpc, int a, double b) {
return rpc->aSetXNumCoefficientsElement(a, b);
}
extern "C" _declspec(dllexport) bool sharpaSetXDenCoefficientsElement(RPCMapper * rpc, int a, double b) {
return rpc->aSetXDenCoefficientsElement(a, b);
}
extern "C" _declspec(dllexport) bool sharpcGenerateBoundingBox(RPCMapper* rpc) {
return rpc->cGenerateBoundingBox();
}
I have created a Qt/C++ .dll for use in a C#/WPF project.
The Qt section code is as below:
cpluspart_global.h:
#ifndef CPLUSPART_GLOBAL_H
#define CPLUSPART_GLOBAL_H
#include <QtCore/qglobal.h>
#if defined(CPLUSPART_LIBRARY)
# define CPLUSPARTSHARED_EXPORT Q_DECL_EXPORT
#else
# define CPLUSPARTSHARED_EXPORT Q_DECL_IMPORT
#endif
extern "C" __declspec(dllexport) void ShowSampleUI();
extern "C" __declspec(dllexport) int Sum(int a, int b);
#endif // CPLUSPART_GLOBAL_H
cpluspart.cpp:
#include "cpluspart.h"
CPlusPart::CPlusPart()
{
}
extern "C" void ShowSampleUI()
{
BenQ *sampleUI = new BenQ();
sampleUI->show();
}
extern "C" int Sum(int a, int b)
{
return a + b;
}
BenQ is an empty QDialog that is just used for tests.
Here is the implementation in C#:
[DllImport("CPlusPart.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void ShowSampleUI();
[DllImport("CPlusPart.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int Sum(int a, int b);
The "Sum" method works properly. However, when I want to call "ShowSampleUI", I receive the following error:
Unhandled exception at 0x00007FFCD125286E (ucrtbase.dll) in CPlusInWPF.exe: Fatal program exit requested.
I would appreciate it if you could kindly help me with this issue.
I do not understand c++ much so I am adding all of the code from which dll was made.
C++ **
**Calculator.h
#ifndef CALCULATOR_H
#define CALCULATOR_H
#include "global.h"
struct CALCULATORSHARED_EXPORT Input {
double a;
double b;
};
struct CALCULATORSHARED_EXPORT Result {
double sum;
double diff;
double prod;
double div;
};
global.h
#ifndef CALCULATOR_GLOBAL_H
#define CALCULATOR_GLOBAL_H
#if defined(CALCULATOR_EXPORTS)
# define CALCULATORSHARED_EXPORT __declspec(dllexport)
#else
# define CALCULATORSHARED_EXPORT __declspec(dllimport)
#endif
#endif // CALCULATOR_GLOBAL_H
calculator.h
#include "calculator.h"
Result calculate( const Input& input) {
Result result;
result.sum = input.a + input.b;
result.diff = input.a - input.b;
result.prod = input.a * input.b;
result.div = input.a / input.b;
return result;
}
C#
[DllImport("Calculator.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern Result calculate(Input input);
[StructLayout(LayoutKind.Sequential)]
public struct Input
{
public double a;
public double b;
};
[StructLayout(LayoutKind.Sequential)]
public struct Result
{
public double sum;
public double diff;
public double prod;
public double div;
};
private void button1_Click(object sender, EventArgs e)
{
Input input;
Result result;
input.a = 5;
input.b = 6;
result = calculate(input);
}
I am getting Unable to find an entry point named 'calculate' in DLL 'Calculator.dll'.
You have to do:
extern "C"
{
CALCULATORSHARED_EXPORT Result calculate(const Input& input)
{
}
}
You don't need to mark CALCULATORSHARED_EXPORT the two structures (Input and Result).
The extern "C" otherwise the name of the function will be mangled, the CALCULATORSHARED_EXPORT otherwise the function won't be exported.
And the C# signature must be:
public static extern Result calculate(ref Input input);
because in C++ it is a Input&.
Clearly then
result = calculate(ref input);
I wrote a C++ dll which I want to use in Unity3D. I put it into Assets/Plugins and wrote a C# script which should access a function of it but I get this error:
EntryPointNotFoundException: Multiply
test.Start () (at Assets/Scripts/test.cs:11)
Manager.h:
extern "C"
{
class Manager
{
public:
__declspec(dllexport) float Multiply(float a, float b);
};
}
Manager.cpp:
#include "Manager.h"
extern "C"
{
float Manager::Multiply(float a, float b)
{
return a * b;
}
}
C# script:
[DllImport("Manager", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
private static extern float Multiply(float a, float b);
void Start()
{
Debug.Log(Multiply(10, 2));
}
Edit: This doesn't work during I'm using a class. To use a class you have to do it like this
I'm trying to learn how to use DLL's in C#. I have a very simple DLL just to test the basics.
// MainForm.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace DLL_Test
{
public partial class Form1 : Form
{
[DllImport("TestDLL.dll",
EntryPoint="?Add##YGHHH#Z",
ExactSpelling = true,
CallingConvention = CallingConvention.StdCall)]
public static extern int Add(int a, int b);
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
int num;
try
{
num = Add(2, 3);
richTextBox1.AppendText(num.ToString() + "\n");
}
catch (DllNotFoundException ex)
{
MessageBox.Show(ex.ToString());
}
catch (EntryPointNotFoundException ex)
{
MessageBox.Show(ex.ToString());
}
}
}
}
And the DLL code:
// TestDLL.cpp
__declspec(dllexport) int __stdcall Add(int a, int b) {
return(a + b);
}
dumpbin returns the following:
ordinal hint RVA name
1 0 00011005 ?Add##YGHHH#Z = #ILT+0(?Add##YGHHH#Z)
This (and other attempts listed below) have all returned the same exception:
System.EntryPointException: Unable to find entry point named "..."
So I am at a loss for how to solve this. Perhaps I do not understand how DllMain functions as the C# entry point for a DLL. TestDLL.dll works when I test it in a C++ application.
After searching for help, I've attempted the following changes:
// TestDLL.cpp
extern "C" __declspec(dllexport) int __stdcall Add(int a, int b) {
return(a + b);
}
Which results in this from dumpbin
ordinal hint RVA name
1 0 00011005 _Add#8 = #ILT+135(_Add#8)
Thus, I changed my C# code:
// MainForm.cs
...
[DllImport("TestDLL.dll",
EntryPoint="_Add",
ExactSpelling = true,
CallingConvention = CallingConvention.StdCall)]
public static extern int Add(int a, int b);
...
I've also tried __cdecl:
// TestDLL.cpp
extern "C" __declspec(dllexport) int __cdecl Add(int a, int b) {
return(a + b);
}
.
// MainForm.cs
...
[DllImport("TestDLL.dll",
EntryPoint="_Add",
ExactSpelling = true,
CallingConvention = CallingConvention.Cdecl)]
public static extern int Add(int a, int b);
...
Perhaps I'm misunderstanding the calling conventions. Any help would be very appreciated. Thank you.
use
extern "C" __declspec(dllexport) int __stdcall Add(int a, int b) { ... }
and
[DllImport("TestDLL.dll", CallingConvention = CallingConvention.Stdcall)]
public static extern int Add(int a, int b);
extern "C" will prevent name mangling with params and return type such as ?Add##YGHHH#Z.
__stdcall will prepend an _ and add #8 : _Add#8 (where 8 is the total size of arguments). Note that it also affects the way parameters are pushed on the stack.
In your DLLImport statement, since you specify CallingConvention.StdCall, you don't need to specify the name mangling. Just give the regular name (Add) and .NET will take care of name mangling (_Add#8).
Note that you must specify the CallingConvention or .NET wouldn't emit the correct code to push arguments on the stack
The following should work.
Unmanged:
extern "C" __declspec(dllexport) int Add(int a, int b)
{
return(a + b);
}
Managed:
class Program
{
[DllImport("TestDLL.dll")]
public static extern int Add(int a, int b);
static void Main()
{
Console.WriteLine(Add(1, 2));
}
}
For future reference: I had a similar problem, solved creating an EMPTY C++ dll project. Probably the standard Visual Studio template causes some trouble.
Refer to this link: http://www.codeproject.com/Articles/9826/How-to-create-a-DLL-library-in-C-and-then-use-it-w