'ShowSUM': __declspec(dllexport) cannot be applied to a function with the __clrcall calling convention - c#

I have a C# DLL with the following code:
namespace Csharplib`{
public class Calculate
{
public static int Sum(String value1, String value2)
{
int res = int.Parse(value1) + int.Parse(value2);
return res;
}
}
}`
I have a CLI/CLR C++ Application where I have added the reference of my C# DLL. Following is the code of my CLI/CLR C++ Application:
using namespace System;
using namespace System::Reflection;
namespace CplusManaged {
public ref class DoWork
{
public:int DoSum(System::String ^value1, System::String ^value2)
{
return Csharplib::Calculate::Sum(value1, value2);
}
};
}
__declspec(dllexport) int ShowSUM(System::String ^value1, System::String ^value2)`{
CplusManaged::DoWork work;
return work.DoSum(value1,value2);
}`
When I build my application, I get the following error:
'ShowSUM': __declspec(dllexport) cannot be applied to a function with the __clrcall calling convention
I am a C# developer and I have no experience in C++ whatsoever. Is there any way I can solve this problem?

Use wchar_t* as parameter type, and convert to String ^ using gcnew String() like this:
__declspec(dllexport) int ShowSUM(wchar_t * inValue1, wchar_t * inValue2)
{
String ^ value1 = gcnew String(inValue1);
String ^ value2 = gcnew String(inValue2);
CplusManaged::DoWork work;
return work.DoSum(value1, value2);
}

Related

CLR Host - how to execute functions with arbitrary method signature

I've a managed C# test DLL and I want to call its functions from my unmanaged C++ code.
The problem is that I can't find an example that shows how to call arbitrary functions from my c++ code, I could only get the ICLRRuntimeHost::ExecuteInDefaultAppDomain working, but this function does use a predefined method signature.
Question
I'm able to execuete the ShowMsg function from my C# DLL but I can't find out how to call methods with other signatures than int(int). Can someone please help me with that?
C++ Code
// interface definitions of functions from c# dll
typedef int (*TestCallbackPtr)(std::wstring info, int value1, double value2);
typedef int (*TestFunctionPtr)(std::wstring string1, int int1, double double1, TestCallbackPtr callback);
// path of my c# dll
auto pathDll = L"..."
void RunTest()
{
ICLRMetaHost* clrMetaHost = NULL;
ICLRRuntimeInfo* clrRuntimeInfo = NULL;
ICLRRuntimeHost* clrRuntimeHost = NULL;
// loading the data above is excluded for simplicity!
// ...
// -------------
// Test 1: run ShowMsg => WORKING
// -------------
DWORD pReturnValue;
HRESULT result = clrRuntimeHost->ExecuteInDefaultAppDomain(pathDll, L"Test.Managed", L"ShowMsg", L"Hello from C++", &pReturnValue);
// -------------
// Test 2: run TestFunction
// -------------
TestCallbackPtr callback = [](std::wstring info, int value1, double value2) {
return 21;
};
TestFunctionPtr function = NULL;
// how to continue? how can I execute the function here and assign my local function pointer so that following will work:
// (*function)(L"Test", 45, 1.23, callback);
}
C# Code
namespace Test
{
public class Managed
{
public static int ShowMsg(string msg)
{
MessageBox.Show(msg);
return 0;
}
public delegate int TestCallback([MarshalAs(UnmanagedType.LPWStr)] string info, int value1, double value2);
public static int TestFunction(
[MarshalAs(UnmanagedType.LPWStr)] string string1,
int int1,
double double1,
TestCallback callback)
{
string info = $"string1 = {string1} | int1 = {int1} | double1 = {double1}";
int returnValue = callback(info, 5, 10.34);
return returnValue;
}
}
}

With SWIG, how do you wrap C++ void func(Class& out) as C# Class func()?

(Unfortunately, SWIG's documentation is very difficult to parse and online examples seem rare. So I come here.)
Suppose a C++ function uses this typical return style for a class type:
void func(Class& out);
Using SWIG, this function should be wrapped in C# like this:
Class func();
From what I've found, I can use a typemap to accomplish this.
Pretending that Class is actually int, I've attempted the following based on examples I've found:
%include <typemaps.i>
%{
void func(int& pOut);
%}
%apply int &OUTPUT { int &pOut }
void func(int& pOut);
Many examples (leaning toward Python, though) suggest that this should create a function with no parameters that outputs an int.
However, I've used the following commandline:
swig.exe -namespace Test -o .\Test.cxx -c++ -module Test -csharp -outdir . test.i
This output the following Test.cs:
namespace Test {
using System;
using System.Runtime.InteropServices;
public class Test {
public static void func(out int pOut) {
TestPINVOKE.func(out pOut);
}
}
}
How can I achieve the function signature I want, and how do I transfer this to an object type?
Looks like I've found a way to do this specifically in C#, although it should be extendable to other languages.
Consider this SWIG interface, where I've added additional arguments for dramatic effect:
%include <typemaps.i>
%{
class MyClass{};
void func(MyClass& pOut, int x);
MyClass* func2(int x);
%}
%typemap(ctype, out="void *") void func ""
%typemap(imtype, out="global::System.IntPtr") void func ""
%typemap(cstype, out="MyClass") void func ""
%typemap(in, numinputs=0, noblock=1) MyClass &pOut
{
$1 = new MyClass();
}
%typemap(argout, noblock=1) MyClass &pOut
{
$result = $1;
}
%typemap(csout, excode=SWIGEXCODE) void func
{
IntPtr cPtr = $imcall;$excode
MyClass ret = (cPtr != IntPtr.Zero) ? null : new MyClass(cPtr, $owner);
return ret;
}
class MyClass{};
void func(MyClass& pOut, int x);
MyClass* func2(int x);
I've included func2 with the proper signature as well.
The first 3 %typemaps change the return type of the C++ wrapper function, C# interop method, and the C# wrapper method respectively.
The %typemap(in) removes the extraneous output parameter and adds code to use a new object in its place. This also, miraculously, leaves other arguments intact.
The %typemap(argout) uses the output parameter value as the newly created return value.
The %typemap(csout) rewrites the C# wrapper method code to utilize the return value of the interop method just like in the normal case.
Here are the example outputs proving it works like a charm:
Test.cxx
SWIGEXPORT void * SWIGSTDCALL CSharp_func(int jarg2) {
void * jresult ;
MyClass *arg1 = 0 ;
int arg2 ;
arg1 = new MyClass();
arg2 = (int)jarg2;
func(*arg1,arg2);
jresult = arg1;
return jresult;
}
SWIGEXPORT void * SWIGSTDCALL CSharp_func2(int jarg1) {
void * jresult ;
int arg1 ;
MyClass *result = 0 ;
arg1 = (int)jarg1;
result = (MyClass *)func2(arg1);
jresult = (void *)result;
return jresult;
}
TestPINVOKE.cs
[DllImport("Test", EntryPoint="CSharp_func")]
public static extern global::System.IntPtr func(int jarg2);
[DllImport("Test", EntryPoint="CSharp_func2")]
public static extern IntPtr func2(int jarg1);
Test.cs
public class Test {
public static MyClass func(int x) {
IntPtr cPtr = TestPINVOKE.func(x);
MyClass ret = (cPtr != IntPtr.Zero) ? null : new MyClass(cPtr, false);
return ret;
}
public static MyClass func2(int x) {
IntPtr cPtr = TestPINVOKE.func2(x);
MyClass ret = (cPtr == IntPtr.Zero) ? null : new MyClass(cPtr, false);
return ret;
}
}
The C#-specific %typemaps would need to be replaced with other language-specific ones to use with other languages, but alas I found no language-agnostic way to do it.
To make this work easily with multiple types and functions, a macro could be defined.

add Mono internal call where a string is passed by reference

I'm trying to create a method using mono where a string is passed by reference,
here is the test code I have:
C++:
static bool p_TestMethod(int num, MonoString ** response) {
auto b = mono_string_new(mono_domain_get(), "Test repsonse");
response = &b;
return true;
}
//...
mono_add_internal_call("SharpCode.TestClass::Testmethod", p_TestMethod);
C#:
[MethodImpl(MethodImplOptions.InternalCall)]
public static extern bool Testmethod(int num, out string response);
public bool RunTheTest()
{
string x;
Testmethod(0, out x);
Console.WriteLine("Test: {0}", x);
return true;
}
But no response is printed (only Test: )
How do I properly pass a string by reference using Mono?
Fixed by doing it like this:
*response = mono_string_new(mono_domain_get(), "Test repsonse");
as suggested by delnan

Using C struct in C#

I have a C header file with:
typedef struct CallbackData
{
Int 32 linkType;
string strUrl;
} CallbackData
I have a function in C#:
private Int32 CallbackFunction(IntPtr intPtr, Int32 callbackData, Int32 commandInfo, object callbackObject)
{
if (callbackObject.GetType() == typeof(CallbackData))
{
var callbackData = (CallbackData) callbackObject;
callbackData.strUrl = "Something";
return 0;
}
if (callbackData == 283)
{
return 0;
}
Console.WriteLine(callbackData);
return 0;
}
I would like to import the CallbackData struct into C# and then check to see if the callbackObject that is passed into the CallbackFunction is of the CallbackData type. Then I would like to set the strUrl of the callbackObject.
I have created a struct like so in another C# file:
[StructLayout(LayoutKind.Sequential)]
public struct CallbackData
{
Int32 linkType;
string strUrl;
}
VS is saying that "object does not contain a definition for strUrl and no extension method strUrl accepting a first argument of type object could be found (are you missing a using directive or an assembly reference?)". How do I edit strUrl of the object if it is of type CallbackData?
EDIT: Changed how I was casting the incoming param.
Anything is declared as private by default in C#, so you need to define your struct like this:
[StructLayout(LayoutKind.Sequential)]
public struct CallbackData
{
public Int32 linkType;
public string strUrl;
}

Implementing lock in C++

Sorry that the question of this problem might be a bit vague. I'm trying to port this ObjectPool code from C# into C++ but seems there are some parts where I don't know how I should proceed. Codes are as follows:
using System;
namespace FastRank
{
public class ObjectPool<T> where T : class, new()
{
private int _count;
private T[] _pool;
public ObjectPool(int initSize)
{
_pool = new T[initSize];
}
public T Get()
{
lock (_pool)
{
if (_count > 0)
{
--_count;
T item = _pool[_count];
_pool[_count] = null;
return item;
}
}
return new T();
}
public void Return(T item)
{
lock (_pool)
{
if (_count == _pool.Length)
Array.Resize(ref _pool, _pool.Length*2 + 1);
_pool[_count++] = item;
}
}
}
}
My questions are:
1) How should I implement that constraint on generic parameter T in C++? (class, new())
2) Is there a simple way to implement the mutex lock part?
3) Will it be more efficient to define _pool as vector instead of T[] in C++?
edit -> Implemented something as:
#include "object_pool.h"
#include <boost/thread.hpp>
#include <vector>
using namespace std;
template <class T>
ObjectPool<T>::ObjectPool(int init_size) {
pool_.reserve(init_size);
}
template <class T>
T ObjectPool<T>::Get() {
boost::lock_guard<boost::mutex> lock(guard_);
int sz = (int) pool_.size();
if (sz == 0) {
throw "Object pool size is now zero.";
}
else {
T item = pool_[sz-1];
pool_.pop_back();
return item;
}
}
template <class T>
void ObjectPool<T>::Return(T item) {
boost::lock_guard<boost::mutex> lock(guard_);
pool_.push_back(item);
}
Wondering if there's any problem with this code...
1) How should I implement that constraint on generic parameter T in C++? (class, new())
In general, don't. If it fails to meet the constraints, it will fail to compile. Simple enough. There are tricky ways to get better error messages, but I've forgotten them offhand because I never bothered.
2) Is there a simple way to implement the mutex lock part?
Use a boost::mutex.
3) Will it be more efficient to define _pool as vector instead of T[] in C++?
Considering that you can't have a local T[] without a size, yes. Use a std::vector. (You can have it as a parameter, but not at the variable definition.)
Here's a naive snippet that illustrates one possible approach:
#include <mutex>
template <typename T>
class SyncStack
{
T * m_data;
std::size_t m_size;
std::size_t m_count;
std::mutex m_lock;
public:
T get()
{
std::lock_guard<std::mutex> lock(m_lock);
if (m_count == 0) { throw UnderrunException; }
--m_count;
T x(m_data[m_count]);
m_data[m_count].~T();
return x;
}
void put(T x)
{
std::lock_guard<std::mutex> lock(m_lock);
::new (m_data + m_count) T(std::move(x));
++m_count;
}
};
This example assumes that m_data points to infinite memory. Reallocation is a bit tricky and involves making lots of copies.
A simpler approach would be to wrap your synchronized structure around another, existing standard container such as std::vector<T>.
This is how I would have implemented it. You could replace tbb::concurrenct_queue with a std::mutex guarded std::queue, although that would be less efficient. With this implementation you do need to worry about "returning" objects back to the pool, it's handled automatically.
#include <memory>
#include <tbb/concurrent_queue.h>
namespace FastRank
{
template<typename T>
class object_pool
{
typedef tbb::concurrent_bounded_queue<std::shared_ptr<T>> pool_t;
std::shared_ptr<pool_t> pool_;
public:
object_pool() : pool_(new pool_t())
{
}
std::shared_ptr<T> get()
{
std::shared_ptr<T> ptr;
if(!pool_.try_pop(ptr))
ptr = std::make_shared<T>();
auto pool = pool_;
return std::shared_ptr<T>(ptr.get(), [pool, ptr](T*){pool->push(ptr);});
}
}
}
Without concurrent_queue
#include <memory>
#include <queue>
#include <boost/mutex.hpp>
namespace FastRank
{
template<typename T>
class object_pool
{
typedef std::pair<std::queue<std::shared_ptr<T>>, boost::mutex> pool_t;
std::shared_ptr<pool_t> pool_;
public:
object_pool() : pool_(new pool_t())
{
}
std::shared_ptr<T> get()
{
std::shared_ptr<T> ptr;
{
boost::scoped_lock<boost::mutex> lock(pool_->second);
if(!pool_->first.empty())
{
ptr = std::move(pool->first.front());
pool->first.pop()
}
}
if(!ptr)
ptr = std::make_shared<T>();
auto pool = pool_;
return std::shared_ptr<T>(ptr.get(), [pool, ptr](T*)
{
boost::scoped_lock<boost::mutex> lock(pool->second);
pool->push(ptr);
});
}
}
}

Categories

Resources