Accessing a C/C++ structure of callbacks through a DLL's exported function using JNA - dll

I have a vendor supplied .DLL and an online API that I am using to interact with a piece of radio hardware; I am using JNA to access the exported functions through Java (because I don't know C/C++). I can call basic methods and use some API structures successfully, but I am having trouble with the callback structure. I've followed the TutorTutor guide here and also tried Mr. Wall's authoritative guide here, but I haven't been able to formulate the Java side syntax for callbacks set in a structure correctly.
I need to use this exported function:
BOOL __stdcall SetCallbacks(INT32 hDevice,
CONST G39DDC_CALLBACKS *Callbacks, DWORD_PTR UserData);
This function references the C/C++ Structure:
typedef struct{
G39DDC_IF_CALLBACK IFCallback;
//more omitted
} G39DDC_CALLBACKS;
...which according to the API has these Members (Note this is not an exported function):
VOID __stdcall IFCallback(CONST SHORT *Buffer, UINT32 NumberOfSamples,
UINT32 CenterFrequency, WORD Amplitude,
UINT32 ADCSampleRate, DWORD_PTR UserData);
//more omitted
I have a G39DDCAPI.java where I have loaded the DLL library and reproduced the API exported functions in Java, with the help of JNA. Simple calls to that work well.
I also have a G39DDC_CALLBACKS.java where I have implemented the above C/C++ structure in a format works for other API structures. This callback structure is where I am unsure of the syntax:
import java.util.Arrays;
import java.util.List;
import java.nio.ShortBuffer;
import com.sun.jna.Structure;
import com.sun.jna.platform.win32.BaseTSD.DWORD_PTR;
import com.sun.jna.win32.StdCallLibrary.StdCallCallback;
public class G39DDC_CALLBACKS extends Structure {
public G39DDC_IF_CALLBACK IFCallback;
//more omitted
protected List getFieldOrder() {
return Arrays.asList(new String[] {
"IFCallback","DDC1StreamCallback" //more omitted
});
}
public static interface G39DDC_IF_CALLBACK extends StdCallCallback{
public void invoke(ShortBuffer _Buffer,int NumberOfSamples,
int CenterFrequency, short Amplitude,
int ADCSampleRate, DWORD_PTR UserData);
}
}
Edit: I made my arguments more type safe as Technomage suggested. I am still getting a null pointer exception with several attempts to call the callback. Since I'm not sure of my syntax regarding the callback structure above, I can't pinpoint my problem in the main below. Right now the relevant section looks like this:
int NumberOfSamples=65536;//This is usually 65536.
ShortBuffer _Buffer = ShortBuffer.allocate(NumberOfSamples);
int CenterFrequency=10000000;//Specifies center frequency (in Hz) of the useful band
//in received 50 MHz wide snapshot.
short Amplitude=0;//The possible value is 0 to 32767.
int ADCSampleRate=100;//Specifies sample rate of the ADC in Hz.
DWORD_PTR UserData = null;
G39DDC_CALLBACKS callbackStruct= new G39DDC_CALLBACKS();
lib.SetCallbacks(hDevice,callbackStruct,UserData);
//hDevice is a handle for the hardware device used-- works in other uses
//lib is a reference to the library in G39DDCAPI.java-- works in other uses
//The UserData is a big unknown-- I don't know what to do with this variable
//as a DWORD_PTR
callbackStruct.IFCallback.invoke(_Buffer, NumberOfSamples, CenterFrequency,
Amplitude, ADCSampleRate, UserData);
EDIT NO 2:
I have one callback working somewhat, but I don't have control over the buffers. More frustratingly, a single call to invoke the method will result in several runs of the custom callback, usually with multiple output files (results vary drastically from run to run). I don't know if it is because I am not allocating memory correctly on the Java side, because I cannot free the memory on the C/C++ side, or because I have no cue on which to tell Java to access the buffer, etc. Relevant code looks like:
//before this, main method sets library, starts DDCs, initializes some variables...
//API call to start IF
System.out.print("Starting IF... "+lib.StartIF(hDevice, Period)+"\n")
G39DDC_CALLBACKS callbackStructure = new G39DDC_CALLBACKS();
callbackStructure.IFCallback = new G39DDC_IF_CALLBACK(){
#Override
public void invoke(Pointer _Buffer, int NumberOfSamples, int CenterFrequency,
short Amplitude, int ADCSampleRate, DWORD_PTR UserData ) {
//notification
System.out.println("Invoked IFCallback!!");
try {
//ready file and writers
File filePath = new File("/users/user/G39DDC_Scans/");
if (!filePath.exists()){
System.out.println("Making new directory...");
filePath.mkdir();
}
String filename="Scan_"+System.currentTimeMillis();
File fille= new File("/users/user/G39DDC_Scans/"+filename+".txt");
if (!fille.exists()) {
System.out.println("Making new file...");
fille.createNewFile();
}
FileWriter fw = new FileWriter(fille.getAbsoluteFile());
//callback body
short[] deBuff=new short[NumberOfSamples];
int offset=0;
int arraySize=NumberOfSamples;
deBuff=_Buffer.getShortArray(offset,arraySize);
for (int i=0; i<NumberOfSamples; i++){
String str=deBuff[i]+",";
fw.write(str);
}
fw.close();
} catch (IOException e1) {
System.out.println("IOException: "+e1);
}
}
};
lib.SetCallbacks(hDevice, callbackStructure,UserData);
System.out.println("Main, before callback invocation");
callbackStructure.IFCallback.invoke(s_Pointer, NumberOfSamples, CenterFrequency, Amplitude, ADCSampleRate, UserData);
System.out.println("Main, after callback invocation");
//suddenly having trouble stopping DDCs or powering off device; assume it has to do with dll using the functions above
//System.out.println("StopIF: " + lib.StopIF(hDevice));//API function returns boolean value
//System.out.println("StopDDC2: " + lib.StopDDC2( hDevice, Channel));
//System.out.println("StopDDC1: " + lib.StopDDC1( hDevice, Channel ));
//System.out.println("test_finishDevice: " + test_finishDevice( hDevice, lib));
System.out.println("Program Exit");
//END MAIN METHOD

You need to extend StdCallCallback, for one, otherwise you'll likely crash when the native code tries to call the Java code.
Any place you see a Windows type with _PTR, you should use a PointerType - the platform package with JNA includes definitions for DWORD_PTR and friends.
Finally, you can't have a primitive array argument in your G39DDC_IF_CALLBACK. You'll need to use Pointer or an NIO buffer; Pointer.getShortArray() may then be used to extract the short[] by providing the desired length of the array.
EDIT
Yes, you need to initialize your callback field in the callbacks structure before passing it into your native function, otherwise you're just passing a NULL pointer, which will cause complaints on the Java or native side or both.
This is what it takes to create a callback, using an anonymous instance of the declared callback function interface:
myStruct.callbackField = new MyCallback() {
public void invoke(int arg) {
// do your stuff here
}
};

Related

(C++/CLI) How to get callbacks from Native Code to Managed Code in C++ CLI?

RANT-BEGIN
Before jumping right into already answered band wagon, please read this paper about SE outdated answers https://ieeexplore.ieee.org/document/8669958
Things changes after a time, and I am afraid Computer science is one of the most if not the most field out there where APIs and Interfaces change radically very very fast. Needless to say that a solution that might worked last month might not after latest feature added to a platform/framework. I humbly request you to not mark this question as answered with decade old post when many mainstream things did not even existed. If you dont know latest solution dont bother about it and leave question for someone else who might.
For a community representative of Computer Science where innovations is everyday thing, it is very toxic, new comer unfriendly and conservative.
END-RANT
This question has already been answered by me and will be accepted tomorrow (SE policy). Thank you for your interest.
Many times you have function pointers in unmanaged context which are called by some kind of events, We will see how it can be achieved with Top-Level Functions and also with member functions of a managed class.
Again, Please dont mark it as answered by linking to a decade old posts.
PS:
So many edits due to unstable internet in third world country, yeah bite me!
unmanaged.cpp
#pragma unmanaged
// Declare an unmanaged function type that takes one int arguments and callbacks
// our function after incrementing it by 1
// Note the use of __stdcall for compatibility with managed code
// if your unmanaged callback uses any other calling convention you can
// UnmanagedFunctionPointerAttribute (check msdn for more info) on your delegate
typedef int(__stdcall* ANSWERCB)(int);//Signature of native callback
int TakesCallback(ANSWERCB fp, int a) {
if (fp) {
return fp(a+1);//Native Callback
}
// This code will be executed when passed without fp
return 0;
}
#pragma managed
managed.cpp
using namespace System;
using namespace System::Runtime::InteropServices;
namespace Callbacks {
// Following delegate is for unmanaged code and must match its signature
public delegate void MyNativeDelegate(int i);
// This delegate is for managed/derived code and ideally should have only managed parameters
public delegate void MyManagedDelegate(int i);
public ref class TestCallback {// Our demo Managed class
private:
GCHandle gch;// kept reference so that it can be freed once we are done with it
void NativeCallbackListener(int i);//unmanaged code will call this function
public:
void TriggerCallback(int i); // Its here for demo purposes, usually unmanaged code will call automatically
event MyManagedDelegate^ SomethingHappened;//plain old event
~TestCallback();//free gch in destructor as its managed.
};
};
void Callbacks::TestCallback::NativeCallbackListener(int i) {
// Callback from Native code,
// If you need to transform your arguments do it here, like transforming void* to somekind of native structure.
// and then pass SomethingHappened::raise with Managed Class/Struct
return SomethingHappened::raise(i); // similar to SomethingHappened.Invoke() in c#
}
void Callbacks::TestCallback::TriggerCallback(int i)
{
MyNativeDelegate^ fp = gcnew MyNativeDelegate(this, &TestCallback::NativeCallbackListener);
// use this if your nativecallback function is not a member function MyNativeDelegate^ fp = gcnew MyNativeDelegate(&NativeCallbackListener);
gch = GCHandle::Alloc(fp);
IntPtr ip = Marshal::GetFunctionPointerForDelegate(fp);
ANSWERCB cb = static_cast<ANSWERCB>(ip.ToPointer());// (ANSWERCB)ip.ToPointer(); works aswell
// Simulating native call, it should callback to our function ptr NativeCallbackListener with 2+1;
// Ideally Native code keeps function pointer and calls back without pointer being provided every time.
// Most likely with a dedicated function for that.
TakesCallback(cb, i);
}
void Callbacks::TestCallback::~TestCallBack() {
gch.Free();//Free GCHandle so GC can collect
}
implementation.cpp
using namespace System;
void OnSomethingHappened(int i);
int main(array<System::String^>^ args)
{
auto cb = gcnew Callbacks::TestCallback();
cb->SomethingHappened += gcnew Callbacks::MyManagedDelegate(&OnSomethingHappened);
cb->TriggerCallback(1);
return 0;
}
void OnSomethingHappened(int i)
{
Console::WriteLine("Got call back with " + i);
}

c# ReadOnlyMemory from pointer

Hi there I have a c native library that is returning me json as char*. What I would like to do in c# is to use this pointer and write it straight to the
this.ControllerContext.HttpContext.Response.BodyWriter;
I'm able to create ReadOnlySpan from the ptr but as far as I can tell PipeWriter only accepts ReadOnlyMemory<byte> which does not have a constructor from IntPtr. Is there a way to create ReadOnlyMemory<byte> from IntPtr or some other way to writer my string from native library withou copying it one extra time?
This answer provides a solution that does not need to copy the entire buffer:
Marshalling pointer to array P/Invoke
TL;DR: Take UnmanagedMemoryManager from Pipelines.Sockets.Unofficial by Marc Gravell.
int* ptr = ...
int len = ...
var memory = new UnmanagedMemoryManager<int>(ptr, len).Memory;
Unfortunately, you still need to allocate the MemoryManager (it must be a class, not a struct).
Thank you for your answers but none of them was without extra copy. I was finally figure it out so in case somebody struggle with it, here is the solution.
So the only way I as able to achieve this is like.
await Response.StartAsync(HttpContext.RequestAborted);
var dest = Response.BodyWriter.GetMemory((int)jsonLen).Pin();
unsafe { memcpy(dest.Pointer), srcPtr, srcLen); }
Response.BodyWriter.Advance(srcLen);
await Response.BodyWriter.FlushAsync(HttpContext.RequestAborted);
Maybe use something like this?
public class Utility
{
public System.ReadOnlyMemory<T> ConvertToReadOnlyMemory(System.ReadOnlySpan<T> input) {
var tmp = new System.Memory<T>();
input.CopyTo(tmp.Span);
return (System.ReadOnlyMemory<T>)tmp;
}
}
However, I think this will involve completely copying the stream into heap storage, which is probably not what you want...
I glad if this could speed up and match to what you wants.
namespace Helper
{
using System;
using System.Runtime.InteropServices;
public static class CStringMapper
{
// convert unmanaged c string to managed c# string
public string toCSharpString(char* unmanaged_c_string)
{
return Marshal.PtrToStringAnsi((IntPtr)unmanaged_c_string);
}
// Free unmanaged c pointer
public void free(char* unmanaged_c_string)
{
Marshal.FreeHGlobal((IntPtr)unmanaged_c_string);
}
}
}
Usage:
using Helper;
/* generate your unmanaged c string here */
try
{
// eg. char* OO7c = cLibFunc();
string cSharpString = CStringMapper.toCSharpString(OO7c);
}
finally
{
// Make sure to freeing the pointer
CStringMapper.free(OO7c);
}

Activation from C++/WinRT DLL

I am trying to write a general wrapper for Windows 10 notifications as a DLL. I've managed to write a DLL that does almost everything the API offers, except I can't get the notification to move to the Action Center. From what I can tell, I need to have a registered COM INotificationActivationCallback for a notification to stay in the Action Center, although I can't understand why.
I want this library to be accessible from an older MinGW-compiled code base, and as such have made an API based on accessing a C++ class using C-style functions. The backing implementation is as follows, with some error handling and other niceties omitted for brevity.
using namespace winrt::Windows;
using namespace UI;
class Win10NotificationManager {
public:
Win10NotificationManager(NotificationCallback, const wchar_t * appUserModelID, void * userdata);
virtual ~Win10NotificationManager();
void createNotification(const wchar_t * xml);
void clearNotifications();
private:
void toast_Failed(const Notifications::ToastNotification &, const Notifications::ToastFailedEventArgs & args);
void toast_Dismissed(const Notifications::ToastNotification &, const Notifications::ToastDismissedEventArgs & args);
void toast_Activated(const Notifications::ToastNotification &, const Foundation::IInspectable & object);
std::wstring appUserModelID_;
NotificationCallback cb_;
void * userdata_;
};
Win10NotificationManager::Win10NotificationManager(NotificationCallback cb, const wchar_t * appUserModelID, void * userdata)
: appUserModelID_(appUserModelID)
, cb_(cb)
, userdata_(userdata)
{
}
Win10NotificationManager::~Win10NotificationManager() {
}
void Win10NotificationManager::createNotification(const wchar_t * xml) {
// Create an XmlDocument from string
Xml::Dom::XmlDocument xmlDoc;
xmlDoc.LoadXml(xml);
// Create a toast object
Notifications::ToastNotification toast(xmlDoc);
// register event handlers
toast.Dismissed(Foundation::TypedEventHandler<Notifications::ToastNotification, Notifications::ToastDismissedEventArgs>(this, &Win10NotificationManager::toast_Dismissed));
toast.Failed(Foundation::TypedEventHandler<Notifications::ToastNotification, Notifications::ToastFailedEventArgs>(this, &Win10NotificationManager::toast_Failed));
toast.Activated(Foundation::TypedEventHandler<Notifications::ToastNotification, Foundation::IInspectable>(this, &Win10NotificationManager::toast_Activated));
// show
auto notifier = Notifications::ToastNotificationManager::CreateToastNotifier(appUserModelID_);
notifier.Show(toast);
}
void Win10NotificationManager::toast_Failed(const Notifications::ToastNotification &, const Notifications::ToastFailedEventArgs & args) {
HRESULT hr = args.ErrorCode();
winrt::check_hresult(hr);
}
void Win10NotificationManager::toast_Dismissed(const Notifications::ToastNotification &, const Notifications::ToastDismissedEventArgs &) {
cb_(nullptr, userdata_);
}
void Win10NotificationManager::toast_Activated(const Notifications::ToastNotification &, const Foundation::IInspectable & object) {
Notifications::IToastActivatedEventArgs args = winrt::unbox_value<Notifications::IToastActivatedEventArgs>(object);
cb_(args.Arguments().begin(), userdata_);
}
void Win10NotificationManager::clearNotifications() {
auto history = Notifications::ToastNotificationManager::History();
history.Clear(appUserModelID_);
}
This works quite well, except for the mentioned missing Action Center persistence. As the DLL is meant to be general (not specific to my one application) I'd like to avoid baking COM activation into the DLL. I don't need to have notifications persisted beyond the lifetime of the calling process, but it would be nice if the notifications weren't gone forever after 5 seconds.
If desired, I could create a gist with a Visual Studio 2017 solution.
In order to use the notification API from the desktop it requires both a registered COM server as well as a shell shortcut. I have no idea why this is necessary, but as far as I can tell that's the only way to make it work. This question comes up fairly often so I wrote a simple C++/WinRT example here:
https://gist.github.com/kennykerr/d983767262118ae0366ef1ec282e428a
Hope that helps.

Pass callbacks with managed parameters and return types between managed and unmanaged C++

I am writing a native C++ project with a managed C++ wrapper that can receive and invoke callbacks from C#. The managed side should be able to retrieve back that callback and trigger on the managed environment as well.
The signature of the said callback is:
// Native C++
typedef EvaluateResult (*NativeFunction) (std::vector<EvaluateResult> args);
// Managed C++ wrapper
delegate EvaluateResultWrapper^ ManagedFunction (List<EvaluateResultWrapper^> args);
The EvaluateResultWrapper is the managed wrapper class for the native class EvaluateResult. The conversion between the EvaluateResult is:
EvaluateResult result;
EvaluateResultWrapper^ wrapper = gcnew EvaluateResultWrapper (result);
result = EvaluateResult (*wrapper.original);
I want to implement the constructor EvaluateResultWrapper::EvaluateResultWrapper (ManagedFunction^ func) that can roughly do the following:
// NOTE: Pseudo code
void EvaluateResultWrapper::EvaluateResultWrapper (ManagedFunction^ func) {
this->func = func; // Store the func as a member to avoid GC
// original is the pointer to the EvaluateResult that this object is wrapping around
this->original = new EvaluateResult ([&func](std::vector<EvaluateResult> args) -> EvaluateResult {
List<EvaluateResultWrapper^>^ argsList; // Convert args from vector to List. Assuming it is done under the hood
EvaluateResultWrapper^ wrapper = func->Invoke (argsList); // Invoke the managed callback
return EvaluateResult (wrapper.GetOriginal ()); // Convert the managed result to the native counterpart
});
}
I know the above code will not work, but the idea I should be able to wrap the managed callback with codes that able to do conversion of both the callback arguments and return types, so that it is native friendly.
Ideally, I can also do the other way around (not important)
// NOTE: Pseudo code
ManagedFunction^ EvaluateResultWrapper::GetFunction (ManagedFunction^ func) {
// if the callback is set by the managed side, return the same callback back
if (this->func != nullptr) return this->func;
// Otherwise, the callback is a native one
NativeFunction nativeFunc = this->original->GetFunction ();
return gcnew ManagedFunction ([&nativeFunc] (List<EvaluateResultWrapper^>^ args) -> EvaluaResultWrapper {
std::vector argsList; // Convert the args from List back to vector. Assuming it is done under the hood
EvaluateResult result = nativeFunc (argsList); // Invoke the native function
return gcnew EvaluateResultWrapper (result); // Convert the native result into the managed one
});
}
I wonder whether this can be done?
A little bit of context: I am writing an external scripting system on native C++ for our games (similar to Lua scripting). The EvaluateResult is a class representing an evaluation result of any statement. It is basically a value coupled with the type. The type can be either number, boolean, string, array, object, or in this case: function callback.
The function callback can be either set within the native C++ (when the interpreter pass the user-defined function in the scripts) or a function set by the host (managed side).
The idea is the host (C# side) should be able to define and set functions into the memory (defining print() function to print into the host console for example). The callback is wrapped as an EvaluateResult class before storing into the the scripting memory.
For inspection purpose, C# side must be able to get the function callback. Therefor, the ability to get the function is nice to have (but not important, since I can always instruct the native side to execute the function for me)

How to use interlocked operations against memory-mapped files in .Net

Is there any way to use the Interlocked.CompareExchange(); and Interlocked.Increment(); methods against values stored in a memory-mapped file?
I'd like to implement a multi-threaded service that will store its data in a memory-mapped file, but since it's multi-threaded I need to prevent conflicting writes, therefore I wonder about the Interlocked operations rather than using explicit locks.
I know it's possible with native code, but can it be done in managed code on .NET 4.0?
OK, this is how you do it! We had to figure this out, and I figured we could give some back to stackoverflow!
class Program
{
internal static class Win32Stuff
{
[DllImport("kernel32.dll", SetLastError = true)]
unsafe public static extern int InterlockedIncrement(int* lpAddend);
}
private static MemoryMappedFile _mmf;
private static MemoryMappedViewStream _mmvs;
unsafe static void Main(string[] args)
{
const int INT_OFFSET = 8;
_mmf = MemoryMappedFile.CreateOrOpen("SomeName", 1024);
// start at offset 8 (just for example)
_mmvs = _mmf.CreateViewStream(INT_OFFSET, 4);
// Gets the pointer to the MMF - we dont have to worry about it moving because its in shared memory
var ptr = _mmvs.SafeMemoryMappedViewHandle.DangerousGetHandle();
// Its important to add the increment, because even though the view says it starts at an offset of 8, we found its actually the entire memory mapped file
var result = Win32Stuff.InterlockedIncrement((int*)(ptr + INT_OFFSET));
}
}
This does work, and works across multiple processes! Always enjoy a good challenge!
TravisWhidden, actually you can use Interlocked.Increment Static method as dan-gph said, you just have to be careful with pointer casting and operator priority, plus parenthesis usage, in facts...
You'll cast a memory pointer (plus the desired offset), into a pointer to an int variable, then you'll use that pointer as a variable. Then you'll have to use it as a variable reference.
Below you'll find the corresponding snippet of yours using .net library instead of external static import.
P&L
class Program
{
private static MemoryMappedFile _mmf;
private static MemoryMappedViewStream _mmvs;
static void Main(string[] args)
{
const int INT_OFFSET = 8;
_mmf = MemoryMappedFile.CreateOrOpen("SomeName", 1024);
_mmvs = _mmf.CreateViewStream(INT_OFFSET, 4);
unsafe
{
IntPtr ptr = _mmvs.SafeMemoryMappedViewHandle.DangerousGetHandle();
Interlocked.Increment(ref (*((int*)(ptr + INT_OFFSET)))
}
}
}