'/clr' and '/Za' command-line options are incompatible - c#

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();
}

Related

Problem with Implementation of QWidget in WPF

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.

Net5 calls the external DLL method and the return value is const char*, C# will directly crash

C++ code:
__declspec(dllexport) const char* Get() {
return "hello word!";
}
C# code:
[DllImport("TestLink.dll")]
public static extern string Get();
The program crashes directly after calling
In any case, when you allocate something from C/C++/Native side, you must use the COM allocator which .NET understands. So there are many ways to return a string, for example:
C++:
extern "C" __declspec(dllexport) void* __stdcall GetBSTR() {
return SysAllocString(L"hello world"); // uses CoTaskMemAlloc underneath
}
extern "C" __declspec(dllexport) void* __stdcall GetLPSTR() {
const char* p = "hello world";
int size = lstrlenA(p) + 1;
void* lp = CoTaskMemAlloc(size);
if (lp)
{
CopyMemory(lp, p, size);
}
return lp;
}
extern "C" __declspec(dllexport) void* __stdcall GetLPWSTR() {
const wchar_t* p = L"hello world";
int size = (lstrlenW(p) + 1) * sizeof(wchar_t);
void* lp = CoTaskMemAlloc(size);
if (lp)
{
CopyMemory(lp, p, size);
}
return lp;
}
And C#
[DllImport("MyDll")]
[return: MarshalAs(UnmanagedType.BStr)]
public static extern string GetBSTR();
[DllImport("MyDll")]
[return: MarshalAs(UnmanagedType.LPWStr)]
public static extern string GetLPWSTR();
[DllImport("MyDll")]
[return: MarshalAs(UnmanagedType.LPStr)]
public static extern string GetLPSTR();

C++ Nested DLL function call from C# gives System.AccessViolationException

My C++ DLL name is MyDLL.dll, which is communicating with TestDLL.dll
Now, I want to call functions from MyDLL.dll in my C# project
Visualization
----------- communicates ------------- communicates ---------------
- C# Code - --------------> - MyDLL.dll - --------------> - TestDLL.dll -
----------- ------------- ---------------
MyDLL.dll is written in C++
TestDLL.dll is written in C
Here is the Code
MyDLL.h
#define MyDLL_API __declspec(dllexport)
extern "C" {
MyDLL_API int sum(int a, int b);
MyDLL_API int do();
}
MyDLL.cpp
#include "MyDLL.h"
#include <Windows.h>
extern "C" {
typedef int (CALLBACK* MYFUNC1)(int, int);
typedef short* (CALLBACK* MYFUNC2)(const char*);
int MyDLL_API sum(int a, int b) // This function works fine
{
return a + b;
}
int MyDLL_API do()
{
int t = -1;
HINSTANCE test_dll;
MYFUNC1 myFunc1;
MYFUNC2 myFunc1;
test_dll = LoadLibraryA("c:\\TestDLL.dll");
if (!test_dll) {
t=0;
}
myFunc1 = (MYFUNC1)GetProcAddress(test_dll, "TestFunc");
if (!myFunc1) {
t=1;
}
myFunc2 = (MYFUNC2)GetProcAddress(test_dll, "AuthFunc");
if (!myFunc2) {
t=2;
}
// If I put 'return t' here, it works fine!
(*myFunc2)("Hello World"); // <-- This line causing the error
return t;
}
}
C# Main Program
class Program
{
public class MyClass
{
[DllImport(#"c:\MyDLL.dll", EntryPoint = "sum")]
public static extern int Sum(int a, int b);
[DllImport(#"c:\MyDLL.dll", EntryPoint = "do")]
public static extern int Do();
}
static void Main(string[] args)
{
int summation = MyClass.Sum(30, 20); // This runs fine.
Console.WriteLine("Sum is: " + summation);
int resultCode = MyClass.Do(); // This causing the ERROR.
Console.WriteLine("Result code is: " + resultCode);
Console.ReadLine();
}
}
Exception Hint
System.AccessViolationException: 'Attempted to read or write protected
memory. This is often an indication that other memory is corrupt.'

C# : DLLImport - DLL Not Found exception

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);

How to create dll in C++ for using in C#

I've a little question to ask you.
I have one C++ source and one header files. The C++ file uses windows.h library, makes operations using serial port(basic operations: read(), write() etc.).
What I want to do is, creating a library using these files, and use that library in my C#.Net solution.
What type of library I need to create?
How can I do it?
After creating library, How can I import it to C# solution?
My best regards.
Code Parts I'm using:
// MathFuncsDll.h
namespace MathFuncs
{
class MyMathFuncs
{
public:
// Returns a + b
static __declspec(dllexport) double Add(double a, double b);
// Returns a - b
static __declspec(dllexport) double Subtract(double a, double b);
// Returns a * b
static __declspec(dllexport) double Multiply(double a, double b);
// Returns a / b
// Throws DivideByZeroException if b is 0
static __declspec(dllexport) double Divide(double a, double b);
};
}
// MathFuncsDll.cpp
// compile with: /EHsc /LD
#include "MathFuncsDll.h"
#include <stdexcept>
using namespace std;
namespace MathFuncs
{
double MyMathFuncs::Add(double a, double b)
{
return a + b;
}
double MyMathFuncs::Subtract(double a, double b)
{
return a - b;
}
double MyMathFuncs::Multiply(double a, double b)
{
return a * b;
}
double MyMathFuncs::Divide(double a, double b)
{
if (b == 0)
{
throw new invalid_argument("b cannot be zero!");
}
return a / b;
}
}
C# import part:
[DllImport("SimpleDll.dll", CallingConvention=CallingConvention.Cdecl)]
public static extern double Add(double a, double b);
static void Main(string[] args)
{
string a = Add(1.0, 3.0));
}
After several comments, here a try:
C++ Code (DLL), eg. math.cpp, compiled to HighSpeedMath.dll:
extern "C"
{
__declspec(dllexport) int __stdcall math_add(int a, int b)
{
return a + b;
}
}
C# Code, eg. Program.cs:
namespace HighSpeedMathTest
{
using System.Runtime.InteropServices;
class Program
{
[DllImport("HighSpeedMath.dll", EntryPoint="math_add", CallingConvention=CallingConvention.StdCall)]
static extern int Add(int a, int b);
static void Main(string[] args)
{
int result = Add(27, 28);
}
}
}
Of course, if the entry point matches already you don't have to specify it. The same with the calling convention.
As mentioned in the comments, the DLL has to provide a C-interface. That means, extern "C", no exceptions, no references etc.
Edit:
If you have a header and a source file for your DLL, it could look like this:
math.hpp
#ifndef MATH_HPP
#define MATH_HPP
extern "C"
{
__declspec(dllexport) int __stdcall math_add(int a, int b);
}
#endif
math.cpp
#include "math.hpp"
int __stdcall math_add(int a, int b)
{
return a + b;
}
You need to compile your C++ code into a dynamic link library and do the following in C#:
class MyClass
{
[DllImport("MyDLL.dll")]
public static extern void MyFunctionFromDll();
static void Main()
{
MyFunctionFromDll();
}
}
You may use C# DllImport and Dllexport for DLL Interop walkthrough as a starting point. And here is the Platform Invoke Tutorial
Hope this helps.
In addition to Lichian's offer to compile to a regular DLL and use p/invoke which is probably the simplest way
You can also create your C++ as a COM component (probably something you don't want to do) and the 3rd option you have is to add a thin layer of C++/CLI
e.g.
using namespace System;
namespace youcomany{ namespace CPPWrapper
{
Wrapper::Function(String^ parameter)
{
//call the rest of you C++ from here
}
}}

Categories

Resources