Passing C++/CLI Class Method as C function pointer - function

I have a third-party C library that provides this header:
//CLibrary.h
#include <Windows.h>
#include <process.h>
typedef void (WINAPI *CLibEventCallback)(int event, void *data);
__declspec(dllexport) bool CLibStart (CLibEventCallback callback, void *data);
// CLibrary.c -- sample implementation
static CLibEventCallback cb;
void _cdecl DoWork (void *ptr)
{
for (int i = 0; i < 10; ++i)
{
cb (i*i, ptr);
Sleep (500);
}
}
__declspec(dllexport) bool CLibStart (CLibEventCallback callback, void *data)
{
cb = callback; // save address for DoWork thread...
_beginthread (DoWork, 0, data);
return true;
}
I need to create a C++/CLI class that can call CLibStart and provide a class method as the function pointer. As suggested below, this needs to be done with GetFunctionPointerForDelegate. Because the delete constructor includes 'this' and doesn't require a static method, I don't need to pass 'this' into CLibStart.
using namespace System;
using namespace System::Runtime::InteropServices;
namespace Sample {
public ref class ManagedClass
{
delegate void CLibraryDelegate (int event, void *data);
private:
CLibraryDelegate^ managedDelegate;
IntPtr unmanagedDelegatePtr;
int someInstanceData;
public:
ManagedClass()
{
this->managedDelegate = gcnew CLibraryDelegate(this, &ManagedClass::ManagedCallback);
this->unmanagedDelegatePtr = Marshal::GetFunctionPointerForDelegate(this->managedDelegate);
this->someInstanceData = 42;
}
void Start ()
{
// since the delegate includes an implicit 'this' (as static function is not needed)
// I no longer need to pass 'this' in the second parameter!
CLibStart ((CLibEventCallback) (void *) unmanagedDelegatePtr, nullptr);
}
private:
void Log (String^ msg)
{
Console::WriteLine (String::Format ("someInstanceData: {0}, message: {1}", this->someInstanceData, msg));
}
void ManagedCallback (int eventType, void *data)
{
// no longer need "data" to contain 'this'
this->Log (String::Format ("Received Event {0}", eventType));
}
};
}
All of this compiles and runs fine using this C# tester:
using System;
using Sample;
namespace Tester
{
class Program
{
static void Main(string[] args)
{
var mc = new ManagedClass();
mc.Start();
Console.ReadKey();
}
}
}
Sample output:
Received Event 0
Received Event 1
Received Event 4
Received Event 9
Received Event 16
Received Event 25
Received Event 36
Received Event 49
Received Event 64
Received Event 81
Outstanding questions:
I have this feeling that I need to use gcroot and/or pin_ptr? If
so, how? where?
Thanks.

gcroot should be in place where ref class stores delegate, like:
gcroot<CLibraryDelegate^> managedDelegate;

Related

how can use exception handling when we are calling a function in java

This is my code i want to call a method with another parameter with use of exception handling i want to sorround with try and catch my calling function. That Have a error of internal local variable is not assigned so i want to sorround it by try catch
how can i sorround a method calling with parameter
public void nik() {
System.out.println("nik or me ghar ja rhe he");
}
public int nik(int time) throws MyMagicExcep {
int a throw ;
System.out.println("nik or me "+a+time+" bje ghar jayege");
return 0;
}
public static void main(String[] args) {
first obj = new first();
// System.out.println();
obj.nik();
try{
System.out.println("harsh bhaiya mja nhi aaya");
obj.nik(1);}
catch(MyMagicExcep e) {
System.out.println("harsh bhaiya mja nhi aaya");
}
obj.nik();
}
}```

How to get thrust::pair first and second use javacpp

From https://github.com/bytedeco/javacpp/wiki/Interface-Thrust-and-CUDA, I write thrust java code. Struct field is public by default, but I use first() method to get the first field value of thrust::pair, error happen.
error: expression preceding parentheses of apparent call must have (pointer-to-) function type
error: macro "offsetof" passed 3 arguments, but takes just 2
{ sizeof(thrust::pair), offsetof(thrust::pair, first) },
So how to get thrust::pair first and second value ?
#Platform(include="<thrust/pair.h>")
#Namespace("thrust")
public class Thrust {
static { Loader.load(); }
#Name("pair<int, double>")
public static class Pair extends Pointer {
static { Loader.load(); }
public Pair(IntPointer key, DoublePointer value){
allocate(key, value);
}
private native void allocate(#ByRef IntPointer k, #ByRef DoublePointer v);
// will happen error: expression preceding parentheses of apparent call must have (pointer-to-) function type
public native IntPointer first();
// will happen error: macro "offsetof" passed 3 arguments, but takes just 2
{ sizeof(thrust::pair<int, double>), offsetof(thrust::pair<int, double>, first) },
public native Pair first(IntPointer p);
}
public static void main(String[] args) {
IntPointer i = new IntPointer(1);
i.put(10);
DoublePointer d = new DoublePointer(1);
d.put(10.0);
Pair p = new Pair(i, d);
System.out.println(p.first());
}
}

Refering within the class to constructor with the this pointer

#include "stdafx.h"
ref class station{
public:
station(){
};
void wrapper_1()
{
this->somefunct(); /*happy*/
};
void wrapper_2()
{
this->station(); /*not happy*/
};
void somefunct(){
System::Console::WriteLine(L"abcde");
};
};
int main(array<System::String^>^ args)
{
station^ temp_1 = gcnew station();
temp_1->wrapper_1();
System::Console::ReadLine();
};
I want to use the this pointer to call my constructor within my station class, it doesn't like this and throws the following error:
error C2273: 'function-style cast' : illegal as right side of '->'
operator.
Can someone explain to me how the constructor differs to other functions when using the pointer this to point to the function. I don't want to take the easy way out using station::station();
example of what I meant to #hans-passant
#include "stdafx.h"
ref class station{
public:
station(int par_1,int par_2)
{
int sum = par_1 + par_2;
System::Console::WriteLine(System::Convert::ToString(sum));
//default value output 13
};
station(){
int pass_1 = 5;
int pass_2 = 8;
station(pass_1,pass_2); /* But why couldn't I use this->station(pass_1,pass_2);*/
};
};
int main(array<System::String^>^ args)
{
station^ obj = gcnew station();
System::Console::ReadLine();
};

JCuda. Reusing already used pointer

I have a trouble working with JCUDA. I have a task to make 1D FFT using CUFFT library, but the result should be multiply on 2. So I decided to make 1D FFT with type CUFFT_R2C. Class responsible for this going next:
public class FFTTransformer {
private Pointer inputDataPointer;
private Pointer outputDataPointer;
private int fftType;
private float[] inputData;
private float[] outputData;
private int batchSize = 1;
public FFTTransformer (int type, float[] inputData) {
this.fftType = type;
this.inputData = inputData;
inputDataPointer = new CUdeviceptr();
JCuda.cudaMalloc(inputDataPointer, inputData.length * Sizeof.FLOAT);
JCuda.cudaMemcpy(inputDataPointer, Pointer.to(inputData),
inputData.length * Sizeof.FLOAT, cudaMemcpyKind.cudaMemcpyHostToDevice);
outputDataPointer = new CUdeviceptr();
JCuda.cudaMalloc(outputDataPointer, (inputData.length + 2) * Sizeof.FLOAT);
}
public Pointer getInputDataPointer() {
return inputDataPointer;
}
public Pointer getOutputDataPointer() {
return outputDataPointer;
}
public int getFftType() {
return fftType;
}
public void setFftType(int fftType) {
this.fftType = fftType;
}
public float[] getInputData() {
return inputData;
}
public int getBatchSize() {
return batchSize;
}
public void setBatchSize(int batchSize) {
this.batchSize = batchSize;
}
public float[] getOutputData() {
return outputData;
}
private void R2CTransform() {
cufftHandle plan = new cufftHandle();
JCufft.cufftPlan1d(plan, inputData.length, cufftType.CUFFT_R2C, batchSize);
JCufft.cufftExecR2C(plan, inputDataPointer, outputDataPointer);
JCufft.cufftDestroy(plan);
}
private void C2CTransform(){
cufftHandle plan = new cufftHandle();
JCufft.cufftPlan1d(plan, inputData.length, cufftType.CUFFT_C2C, batchSize);
JCufft.cufftExecC2C(plan, inputDataPointer, outputDataPointer, fftType);
JCufft.cufftDestroy(plan);
}
public void transform(){
if (fftType == JCufft.CUFFT_FORWARD) {
R2CTransform();
} else {
C2CTransform();
}
}
public float[] getFFTResult() {
outputData = new float[inputData.length + 2];
JCuda.cudaMemcpy(Pointer.to(outputData), outputDataPointer,
outputData.length * Sizeof.FLOAT, cudaMemcpyKind.cudaMemcpyDeviceToHost);
return outputData;
}
public void releaseGPUResources(){
JCuda.cudaFree(inputDataPointer);
JCuda.cudaFree(outputDataPointer);
}
public static void main(String... args) {
float[] inputData = new float[65536];
for(int i = 0; i < inputData.length; i++) {
inputData[i] = (float) Math.sin(i);
}
FFTTransformer transformer = new FFTTransformer(JCufft.CUFFT_FORWARD, inputData);
transformer.transform();
float[] result = transformer.getFFTResult();
HilbertSpectrumTicksKernelInvoker.multiplyOn2(transformer.getOutputDataPointer(), inputData.length+2);
transformer.releaseGPUResources();
}
}
Method which responsible for multiplying uses cuda kernel function.
Java method code:
public static void multiplyOn2(Pointer inputDataPointer, int dataSize){
// Enable exceptions and omit all subsequent error checks
JCudaDriver.setExceptionsEnabled(true);
// Create the PTX file by calling the NVCC
String ptxFileName = null;
try {
ptxFileName = FileService.preparePtxFile("resources\\HilbertSpectrumTicksKernel.cu");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// Initialize the driver and create a context for the first device.
cuInit(0);
CUdevice device = new CUdevice();
cuDeviceGet(device, 0);
CUcontext context = new CUcontext();
cuCtxCreate(context, 0, device);
// Load the ptx file.
CUmodule module = new CUmodule();
cuModuleLoad(module, ptxFileName);
// Obtain a function pointer to the "add" function.
CUfunction function = new CUfunction();
cuModuleGetFunction(function, module, "calcSpectrumSamples");
// Set up the kernel parameters: A pointer to an array
// of pointers which point to the actual values.
int N = (dataSize + 1) / 2 + 1;
int pair = (dataSize + 1) % 2 > 0 ? 1 : -1;
Pointer kernelParameters = Pointer.to(Pointer.to(inputDataPointer),
Pointer.to(new int[] { dataSize }),
Pointer.to(new int[] { N }), Pointer.to(new int[] { pair }));
// Call the kernel function.
int blockSizeX = 128;
int gridSizeX = (int) Math.ceil((double) dataSize / blockSizeX);
cuLaunchKernel(function, gridSizeX, 1, 1, // Grid dimension
blockSizeX, 1, 1, // Block dimension
0, null, // Shared memory size and stream
kernelParameters, null // Kernel- and extra parameters
);
cuCtxSynchronize();
// Allocate host output memory and copy the device output
// to the host.
float freq[] = new float[dataSize];
cuMemcpyDtoH(Pointer.to(freq), (CUdeviceptr)inputDataPointer, dataSize
* Sizeof.FLOAT);
And the kernel function is next:
extern "C"
__global__ void calcSpectrumSamples(float* complexData, int dataSize, int N, int pair) {
int i = threadIdx.x + blockIdx.x * blockDim.x;
if(i >= dataSize) return;
complexData[i] = complexData[i] * 2;
}
But when I'm trying to pass the pointer which points to the result of FFT (in device memory) to the multiplyOn2 method, it throws the exception on cuCtxSynchronize() call. Exception:
Exception in thread "main" jcuda.CudaException: CUDA_ERROR_UNKNOWN
at jcuda.driver.JCudaDriver.checkResult(JCudaDriver.java:263)
at jcuda.driver.JCudaDriver.cuCtxSynchronize(JCudaDriver.java:1709)
at com.ifntung.cufft.HilbertSpectrumTicksKernelInvoker.multiplyOn2(HilbertSpectrumTicksKernelInvoker.java:73)
at com.ifntung.cufft.FFTTransformer.main(FFTTransformer.java:123)
I was trying to do the same using Visual Studion C++ and there no problems with this. Could you please help me.
P.S.
I can solve this prolem, but I need to copy data from device memory to host memory and then copy back with creating new pointers every time before calling new cuda functions, which slows my program executing.
Where exactly does the error occurs at which line?
The Cuda error can also be a previous error.
Why do you use Pointer.to(inputDataPointer), you already have that device pointer. Now you pass a pointer to the device pointer to the device?
Pointer kernelParameters = Pointer.to(Pointer.to(inputDataPointer),
I also recommend to use "this" qualifier or any other marking to detect instance variables. I hate and refuse to look through code, especially as nested and long as your example if I cannot see which scope the variable in methods have trying to debug it by just reading it.
I don't wanna ask myself always where the hell comes this variable from.
If a complex code in a question at SO is not formatted properly I don't read it.

Custom SWIG Wrapping to Handle Nested C Structures

I have the below C struct that has a couple nested structures that have proven to be difficult to deal with using my knowledge of SWIG. Everything below is easily wrapped by SWIG execept for saddr (C socket address) and mac[6] (C array representing a MAC address). Since SWIG gives me the pointer value (SWIGTYPE_p_unsigned_char and SWIGTYPE_p_sockaddr), I would like to somehow call a helper C function to convert the pointer to a char*. I have the helper function, but I don't know the best way to plug this into SWIG. Is there any way to configure the getMac() and getSaddr() to call the helper function?
C Structure Trying To Wrap:
%rename (Details) details_t_;
typedef struct details_t_ {
uint16_t code;
char *name;
**sockaddr *saddr;**
uint32_t saddr_len;
uint8_t flag;
ios_boolean is_child;
**unsigned char mac[6];**
} details_t;
Generated Java Code:
public void setMac(SWIGTYPE_p_unsigned_char value) {
TestJNI.Details_mac_set(swigCPtr, this, SWIGTYPE_p_unsigned_char.getCPtr(value));
}
public SWIGTYPE_p_unsigned_char getMac() {
long cPtr = TestJNI.Details_mac_get(swigCPtr, this);
return (cPtr == 0) ? null : new SWIGTYPE_p_unsigned_char(cPtr, false);
}
public void setSaddr(SWIGTYPE_p_sockaddr value) {
TestJNI.Details_saddr_set(swigCPtr, this, SWIGTYPE_p_sockaddr.getCPtr(value));
}
public SWIGTYPE_p_sockaddr getSaddr() {
long cPtr = TestJNI.Details_saddr_get(swigCPtr, this);
return (cPtr == 0) ? null : new SWIGTYPE_p_sockaddr(cPtr, false);
}
Proposed SWIG.i Changes:
%module Test
%rename (realId) details_t_::mac;
%typemap(javacode) struct details_t_ %{
public String getMac() {
return Test.getMacAddressAsString(this);
//this is a pointer to details_t_ struct
}
%};
%rename (Details) details_t_;
typedef struct details_t_ {
uint16_t code;
char *name;
**sockaddr *saddr;**
uint32_t saddr_len;
uint8_t flag;
ios_boolean is_child;
**unsigned char mac[6];**
} details_t;
You can do this with a javacode typemap, e.g.:
%module test
%rename (realId) Sample::id;
%typemap(javacode) struct Sample %{
public byte getId() {
return 100-getRealId(); // Transform the real call
}
public void setId(byte value) {
setRealId(value+100);
}
%};
struct Sample {
char id;
};
Renames the generated getId() and setId(), but provides a Java get/set which can be written in terms of the SWIG generated (but renamed) one. You might want to make the SWIG generated ones private though.