How to keep an object “persistent” in a C# dll? - c#

I have written a dll in C#, offering a class for use. The dll is called by a C program that I have written. (It’s a plugin to some program. I have to write the plugin’s code in C, but I want to use the functionality of .NET, therefore the dll).
In the dll, I want to open up a stream and do other stuff that should be persistent between two calls to the dll. That is represented in the following code by the private member Connector.
namespace myCSharpDll
{
// the c++ program calls this methods
public interface IAccess
{
double Initialize();
double Timestep(double time, double[] values);
...
}
// E is the beginning of another program my dll should connect to, therefore the names
public class EAccess : IAccess
{
// EConnector is another class I defined in the same dll
private EConnector Connector;
public double InitializeE()
{
Connector = new EPConnector();
}
public double Timestep(double time, double[] values)
{
return Connector.Connect();
}
When I make a call to InitializeE() and later one to Timestep() the Connector oject points to NULL.
What do I have to do that when I call Timestep() from my C code, that I can access the before created instance of Connector?
I probably search in the wrong direction at all. Any tips are appreciated.

If I am not wrong you want to maintain a single object throughout the use of dll in c. If that is the case try something similar to singleton pattern.
http://en.wikipedia.org/wiki/Singleton_pattern
What singleton emphazises is you create only single object for a class and use it to perform all the work you need. Basically you might need a function that does something like this,
public class EAccess : IAccess
{
private static EConnector Connector
public EConnector getConnector(){
if(Connector == null){
Connector = new EConnector();
}
return Connector;
}
public double Timestep(double time, double[] values)
{
return getConnector().Connect();
}
};
Even though this is not the traditional way of doing things using singleton but I think it still does the work. I may be wrong. Please correct me if I have misunderstood something.

Thanks SLaks for asking for my C/C++ code. That is where the problem was located. It was simpler than I thought. I found the mistake while putting together the code to show you.
I know that C and C++ is not the same, the plugin structure is just a little weird. Most of the code was generated by a wizard. I just had to fill in my code. It's a cpp file, but the code seems to be C. Well, I think that is off topic.
Here it is, I extraced the most important lines.
// the dll is connected via COM, using the type library file that regasm generated
#import "[path]\myCSharpDll.tlb" raw_interfaces_only
using namespace myCSharpDll;
static void OnActivate (IfmDocument, Widget);
//off topic: this are the weird lines the wizard put in my way
#ifdef __cplusplus
extern "C"
#endif /* __cplusplus */
// when the plugin is called by the host program, this function is called
static void OnActivate (IfmDocument pDoc, Widget button)
{
InitializeIntermediate(pDoc);
Timestep1(...);
}
static void InitializeIntermediate(IfmDocument pDoc)
{
// Initialize COM.
HRESULT hr = CoInitialize(NULL);
IEPAccessPtr pIEPAccess(__uuidof(EPAccess));
double result = -1;
pIEPAccess->InitializeEP (&result);
...
}
static void Timestep1(...)
{
IEPAccessPtr pIEPAccess(__uuidof(EPAccess));
double result = -1.1;
pIEPAccess->Timestep (...);
...
// now I get a wrong result back here, because this call leads to nowhere as
// the connector object in the dll is void
}
I realized that I am requesting a second instance with that line
IEPAccessPtr pIEPAccess(__uuidof(EPAccess));
So I changed that pointer to one single instance and everything is fine. Thanks for your comments!

Related

Unmanaged code with file access fails in a .NET/C# application

Here's the scenario I am confronted with:
in a simple DLL, written in C, there are functions which access files, for example:
DLL_EXPORT void Virt_Hello(void) {
FILE *f = fopen("Hello_world", "w");
if (f) {
fprintf(f, "Hello world!\n");
}
fclose(f);
}
in the managed code:
[SuppressUnmanagedCodeSecurity]
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void Virt_HelloDelegate();
private IntPtr m_helloPtr;
m_helloPtr = GetProcAddress(m_libraryPtr, "Virt_Hello");
Virt_Hello = Virt_HelloDelegate)Marshal.GetDelegateForFunctionPointer(m_helloPtr, typeof(Virt_HelloDelegate));
and later, this function is called as:
[SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)]
public void Hello()
{
Virt_Hello();
}
I've been reading for the last couple of days pretty much everything I could find on this topic however it still doesn't work: the file is not open, and the calling managed code/process just hangs - no exceptions are thrown either.
Tried StdCall calling convention, changed several parameters on the SecurityPermission attribute - to no avail. I've even made sure all assembly dependencies are signed.
Of course I would prefer to integrate it through C++/CLI instead of PInvoke-ing however the DLL is a blackbox for me.
Any help or suggestion how to go forward would be much appreciated.
I'm pretty sure I'm missing something obvious but right now I just can't see it.
My best regards to the community!

C++ function trigger C# function

Basically my code is looks like below
Managed.dll
Managed.cs
class MyManagedClass
{
public ShowMessage()
{
System.out.println("My Message");
}
}
Wrapper.dll
ref class Wrapper
{
};
Native.lib
class NativeClass
{
public:
void NativeMessage()
{
cout<<"Print Message";
}
}
Main
void main
{
NativeClass ob;
ob.NativeMessage();
}
my issue is whenever the "ob.NativeMessage();" called, somehow MyManagedClass::ShowMessage() has to be triggered.
And more impotent Native.lib linked in Wrapper.dll and Wrapper.dll referenced in Managed.dll.
Can any one help me on this.
If you're running strictly from a C++ environment, you will want to host a .NET runtime in your C++ application. If you're running from a .NET environment, that part is already done and you will need to pass a delegate to the C++ code to be called later (this, by the way, is fraught with problems as the .NET runtime up to at least version 3.0 can and will garbage collect delegates out from under you).

How to use Android KitKat EvaluateJavascript in Xamarin.Android/Monodroid and retrieve result?

For Xamarin.iOS/Monotouch it is simple to retrieve a string when evaluating javascript.
e.g.
string elementValue = browser.EvaluateJavascript("document.getElementById('Id').value");
if(elementValue != "")
{
DoSomething();
}
Could anybody provide an example of how to do this for Xamarin. Android/Monodroid Android kitkat and above using Evaluatejavascript()?
Specifically how to use/setup IValueCallback Synchronously.
#ksasq's answer is essentially correct but needs some small changes.
First of all, make sure you have Xamarin Android 4.12 installed which adds bindings for KitKat.
Then, since WebView.evaluateJavascript hasn't been bound in C# flavor, you have to create a class implements IValueCallback. The tricky part is that class has to be inherited from Java.Lang.Object.
An example of the class would be like:
private class MyClass : Java.Lang.Object, IValueCallback
{
public void OnReceiveValue(Java.Lang.Object value)
{
//Here goes your implementation.
}
}
Android's WebView executes JavaScript asynchronously and passes the result of the execution in a ValueCallback later.
I'm not familiar with Xamarin exactly, but if you can share some of your Android C# code, may be able to help better.
From a Java perspective, where my experience lies:
Essentially, you need to instantiate a ValueCallback object that implements the onReceiveValue function. When the javascript that you have evaluated finishes executing, the function you declared will be executed, passing in the result of that evaluation as a paramter that is string of JSON. You should then be able to retrieve the result from that JSON.
Hope this helps!
Update: cobbling together some C# that might help. Caveat: I've never written a line of c# before this. But hopefully if it's not quite right will set you on the right path :-)
class JavaScriptResult : public IValueCallback {
public void OnReceiveValue(Java.Lang.Object result) {
Java.Lang.String json = (Java.Lang.String) result;
// |json| is a string of JSON containing the result of your evaluation
}
}
Then you can presumably say something along the lines of
web_view.EvaluateJavaScript("function() { alert('hello world'); return 42; }()",
new JavaScriptResult());

Send code to be executed on server in C# - like Java RMI

This is example code in java.
Shared interfaces:
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface Compute extends Remote {
public Object executeTask(Task t) throws RemoteException;
}
Task (this will be passed as parameter):
import java.io.Serializable;
public interface Task extends Serializable {
public Object execute();
}
Server:
import java.rmi.Naming;
import java.rmi.RMISecurityManager;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
public class ComputeEngine extends UnicastRemoteObject implements Compute {
public ComputeEngine() throws RemoteException {
super();
}
public Object executeTask(Task t) {
return t.execute();
}
public static void main(String[] args) {
setRmiCodebase();
System.setSecurityManager(new RMISecurityManager());
try {
Compute engine = new ComputeEngine();
Naming.rebind("//localhost:1099/Compute", engine);
System.out.println("ComputeEngine started.");
} catch (Exception ex) {
ex.printStackTrace();
}
}
private static void setRmiCodebase() {
String codebase = System.getProperty("java.rmi.server.codebase");
if (codebase != null)
return;
// set codebase based on location of this clsas (is it in jar or filesistem?)
}
}
Client:
import java.math.BigDecimal;
/**
* Calculates Pi to arbitrary number of digits:
*/
public class Pi implements Task {
public Pi(int digits) {
this.digits = digits;
}
public Object execute() {
return computePi(digits);
}
public static BigDecimal computePi(int digits) {
// compute Pi
}
}
Client main:
import java.math.BigDecimal;
import java.rmi.Naming;
import java.rmi.RMISecurityManager;
public class ComputePi {
public static void main(String[] args) {
setRmiCodebase();
System.setSecurityManager(new RMISecurityManager());
try {
Compute comp = (Compute)Naming.lookup("//localhost:1099/Compute");
Pi task = new Pi(100);
BigDecimal pi = (BigDecimal)comp.executeTask(task);
System.out.println(pi);
} catch (Exception ex) {
ex.printStackTrace();
}
}
private static void setRmiCodebase() {
String codebase = System.getProperty("java.rmi.server.codebase");
if (codebase != null)
return;
// set codebase based on location of this clsas (is it in jar or filesistem?)
}
}
As you can see, code (not just data) from client is transfered to server and executed there and result of computation is returned. Server does not know that class Pi exists, it only knows about Task interface.
I need something like this to work in .net environment (C# if it is important). WCF would be nice, but I am looking for the most straightforward solution, so WCF is not compulsory. I am not sure even what keyword to use to google documetation or solution for this.
Any help will be appreciated.
Afaik .NET doesn't support this out of the box - you can do remoting but that won't (as is) let you run code from the client on the server. I think you would have to implement something that transfers the dll containing the code you want to execute to the server, and then probably load that dll in a separate AppDomain (because you can't unload dll's unless you load them into a separate AppDomain), and then have a way to specify the class to run.
.NET does not natively support "sending code" to be executed on another computer. Typically the necessary code would be compiled to assemblies and pre-installed on the server before it is called by the client. This is true of both remoting and WCF. You could have a two-way remoting situation where the server calls back to a method on the client via WCF, but I suspect this is not what you want. The only way I'm aware of to really run dynamic code on the server is to generate dynamic code, send it to the server as a string, and then have the server compile it to an in-memory assembly on the fly and then execute it. If you are interested in doing so, take a look at my answer to a similar question:
Autovivified properties?
However, it's not exactly something I would suggest in most cases. I would suggest you rethink your design, first, to see if there is any way to do what you need in a typical ".NET way".
What You want is .NET Remoting.
Here's link to article showing how to migrate from RMI to .NET Remoting.
But according to this MSDN article this is a legacy technology and You should use WCF.
Edit:
You can't "just like that" get .NET Remoting functionality with WCF.
Here you can read discussion about porting from .NET Remoting to WCF.
But if you don't know WCF at all You shoud start here. And You probably won't get your results fast :).
This MSDN page has more or less this exact use case you described. You just need to modify the ServiceContract
http://msdn.microsoft.com/en-us/library/system.servicemodel.netnamedpipebinding.aspx
You would probably only need to modify this part:
[ServiceContract(Namespace = "http://UE.Samples")]
public interface ICalculator
{
[OperationContract]
double Add(double n1, double n2);
}
// Service class which implements the service contract.
public class CalculatorService : ICalculator
{
public double Add(double n1, double n2)
{
return n1 + n2;
}
Instead of scalar values put your executeTask method with parameter of your own class there.
I don't believe .NET has a built-in solution for transferring executable code from client to server. Assuming the security constraints allow it, you might consider sending interpretable code such as Python or JavaScript which could be executed server-side via IronPython or IronJS respectively. If C# is a requirement (and you still have access to the source code), sending the source and compiling server-side (via Roslyn or the Mono's evaluator).

Error calling an unmanaged windows DLL from a C# WPF application

I am working on a project that requires implementing am unmanaged windows DLL. The DLL is used to communicate with a USB device. My code is in C# and WPF.
To initialize the DLL I call a function called:
InitTimerDll(Int32 wHandle, ref dllInitParams initParams);
When calling this function I have to pass a struct called dllInitParams and the Handle that the control is bound to.
I am using DllImport for function pointer as such:
[DllImport("myDll.dll")]
public static extern void InitTimerDll(Int32 wHandle, ref dllInitParams initParams);
Here is my struct:
public struct dllInitParams
{
public UInt16 simp;
public UInt16 simt;
}
All of the above are in a separate class called myDllInterface.cs. Here is how I call the InitTimerDll function from my WPF form:
public IntPtr Handle
{
get { return (new System.Windows.Interop.WindowInteropHelper(this)).Handle; }
}
private void initTime_Click(object sender, RoutedEventArgs e)
{
myDllInterface.dllInitParams initParams = new myDllInterface.dllInitParams();
initParams.simp = 0;
myDllInterface.InitTimerDll(this.Handle.ToInt32(), ref initParams);
}
The first part of the above code explains how I get the handle and the initTime_Click shows how I initialize the struct, call the initTimeDll function by passing the handle and the struct to it. I have copied the dll file in the directory that the code runs in. My code compiles just fine but it creates an error when I click on the initTime button.
Error:
An unhandled exception of type 'System.AccessViolationException' occurred in ProbeCTRL.exe
Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
Why is this happening?
Without knowing exactly what the InitTimerDll() function does with the 'this' pointer, I would focus on the params structure. Try adding a structure layout markup like the following:
[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct dllInitParams
{
public UInt16 simp;
public UInt16 simt;
}
Also, double check that your structure is complete and accurate.
I found the problem. The code is fine the problem was the dll file, which was corrupted. A proper copy of the dll file took care of the problem. When using dll in your codes it is quite important to make sure you have accurate information, function calls, data types to passed and so on.
Thanks everyone for your help.
Have a look at the PInvoke tutorial: http://msdn.microsoft.com/en-us/library/aa288468%28v=vs.71%29.aspx
as Jim Gomes points out:
[StructLayout(LayoutKind.Sequential)]
or something similar is definitely important.
Also, you're only initializing one of the variables in your struct.

Categories

Resources