My application consist of C# code with unmanaged C dll calls.
In my C# code I have an object/class where its properties are both system types such as string and int and other objects I have defined.
I would like to pass this complex (Graph.cs) object to my C (dll) code, what implementation would you suggest here?
I have tried moving structs but I fail to do so with anything other then string and int.
Thanks.
Code:
public Class Grpah {
TupleCollection m_TupleCollection;
int m_nGeneralIndex;
bool m_bPrintWRF;
string m_sLink;
}
public Class TupleCollection {
IList<Tuple> _collection;
}
public Class Tuple {
Globals.TupleType m_ToppleType;
ArrayList m_Parameters;
}
public class TupleArgs {
public string Value { get; set; }
public Globals.PAS PAS;
public RefCollection RefCollection { get; set; }
public int Time{ get; set; }
}
public class RefCollection {
public List<int> SynSet{ get; set; }
public Globals.PAS PAS;
}
Try:
How to: Marshal Structures Using PInvoke
I think the easiest way for you to make progress is to modify the native code, giving it the ability to work with CLR types.
Now, you're almost certainly using Visual Studio, and hopefully it's VS2005 or later. This means that although your existing native code is in C, you have the option to delve into a little C++. And not only that - you also have C++/CLI.
So I would make a new C++/CLI DLL, and link your C library to it, so that it can call into the C code. Then write a thin translation layer in the C++/CLI library: it will expose true CLR classes (written with ref class) and will call onto the native C code.
e.g. in a C header:
void do_something_with_foo_data(int a, int b, int c);
In C++/CLI:
public ref class FooWrapper
{
static void DoSomethingWithFoo(Foo ^foo)
{
// pick apart the Foo class and pass the pieces on to the C function
do_something_with_foo_data(foo->A, foo->B, foo->C);
}
};
In C#:
public class Foo
{
public int A { get; set; }
public int B { get; set; }
public int C { get; set; }
}
...
var foo = new Foo { A = 1, B = 2, C = 3 };
FooWrapper.DoSomethingWithFoo(foo);
When I did this I used Marshal exclusively. This was with standard C for the native code. I did not want to convert my C code to "managed C++" or whatever they call it :-)
The hard and tedious part is that you have to manually marshal your data structure into something that maps directly to the receiving C function. In my case, I had to create separate structs for each data bearing C#-class I wanted to send. In essence, you should convert your nice C# object hierarchy into a more basic form consisting of structs which you then marshal into a memory chunk which you then use as an argument in your native call.
You should use the method Marshal.AllocHGlobal for allocing memory and Marshal.StructureToPtr for copying your C# struct to that memory and then Marshal.FreeHGlobal to free it.
Once you have your IntPtr (from StructureToPtr), you should be able to simply call your C-dll with that pointer as argument. Note that the struct you are sending to your C function must have the same layout as the native C struct, or you will get very odd results.
Returning data is pretty much the same thing, but you are using the opposite functions (PtrToStructure etc) instead.
Thats the basic of it anyway.
Your model looks pretty complicated, and incomplete: Tuple.m_parameters is an ArrayList, so it can contain just about anything, and the Globals.PAS type is not defined here.
Perhaps you should think of a different strategy: in your DLL, make a small model that contains whatever you need in your C code, and make it as simple as possible (but not simpler!).
Then, learn whatever you need to marshal that C model from your managed code, and fill in the model from your Graph.cs class. Preferably, Graph.cs shouldn't be responsible to do this, your marshalling code should be.
Related
I have a relatively simple C#class that I would like to marshal into a VB project. It looks like this (I simplified a bit for this post):
[Guid("AAAAAAAA-AAAA-AAAA-AAAA-123456789ABC", ClassInterface(ClassInterfaceType.AutoDual), ComVisible(true)]
[ProgId("MyBiz.MyResponse")
[Serializable]
public class MyResponse
{
public bool Success { get; set; }
public int ID{ get; set; }
public string Location{ get; set; }
public ArrayList Messages { get; set; }
}
Messages contains 0 or more strings. I compile this and create a type library to be used by VB6. Everything work well in terms of data getting passed from the simple types, but the Messages variable, while the VB runtime recognizes it as an ArrayList, does not contain any data in it even when it should. What am I missing, in terms of marshaling the data? I know that generics do not marshal, but I believe an ArrayList does. Am I missing an attribute, or something else?
No need to offer alternative solutions, as I am asking this because I want to know how to do it, not because I don't have alternatives if I can get this to work. Thanks!
One way to handle this is to use a COM SafeArray to pass data back and forth from .NET to COM. I have had better luck with this technique than with a ArrayList. The declaration for your Messages could look like:
[return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)]
public string[] Messages
This would be seen in VB6 or similar COM client as
Public Messages() as String
a COM SafeArray of Strings.
We can pass data between functions by using class objects. Like i have class
public class AddsBean
{
public long addId{get;set;}
public int bid { get; set; }
public long pointsAlloted { get; set; }
public string userId { get; set; }
public enum isApproved { YES, NO };
public DateTime approveDate { get; set; }
public string title { get; set; }
public string description { get; set; }
public string Link { get; set; }
public DateTime dateAdded { get; set; }
}
We can call function like public List<AddsBean> getAdds(string Id). This approach is good when you need all the variables of class. But what if you need only 2 or 3 variables of class?
Passing object of class is not good because it will be wastage of memory. Another possible solution is to make different classes of lesser variables but that is not practical.
What should we do that will best possible solution to fulfill motive and best according to performance also?
In Java - "References to objects are passed by value".. So, you dont pass the entire object, you just pass the reference to the object to the called function.
EG:
class A{
int i;
int j;
double k;
}
class B{
public static void someFunc(A a) // here 'a' is a reference to an object, we dont pass the object.
{
// some code
}
public static void main(String[] args){
A a = new A();
B.someFunc(a); // reference is being passed by value
}
}
first of all, as Java is pass by value and references typed, there is no need to worry about the memory wastage.
next, as you have mentioned, it is not good to pass all the object if you do not need them all, in some situation, it's true. as you need to protect your data in instance, thus you can use different granularity of class, for instance:
class A
{id, name}
class B extends A
{password,birthday}
by refer to different class you can control the granularity yourself, and provide different client with different scope of data.
But in some condition, you need to use a instance to store all data in the whole application, like configure data in hadoop, or some other configuration related instance.
Try to choose the most suitable scope!
If you're sure that this is the source of problems and you don't want to define a new class with a subset of the properties, .NET provides the Tuple class for grouping a small number of related fields. For example, a Tuple<int, int, string> contains two integers and a string, in that order.
public Tuple<string, long, DateTime> GetPointsData()
{
AddsBean bean = ... // Get your AddsBean somehow
return Tuple.Create<string, long, DateTime>(bean.userId, bean.pointsAlloted, bean.approveDate);
}
Once this method goes out of scope, there is no longer a live reference to the object bean referred to and will be collected by the garbage collector at some point in the future.
That said, unless you're sure that instances of the AddsBean class are having a noticeable negative effect on the performance of your app, you should not worry about it. The performance of your application is probably affected far more by other operations. Returning a reference type (a type defined with class instead of struct) only passes a reference to the object, not the data of the object itself.
Ok so lets say I have a structure A like that:
Struct A{
private String _SomeText;
private int _SomeValue;
public A(String someText, int SomeValue) { /*.. set the initial values..*/ }
public String SomeText{ get { return _SomeText; } }
public int SomeValue{ get { return _SomeValue; } }
}
Now what I want to be able to do is to return that Structure A as a result of a method in a Class ABC, like that:
Class ABC{
public A getStructA(){
//creation of Struct A
return a;
}
}
I don't want any programmer using my library (which will have Struct A and Class ABC and some more stuff) to ever be able to create an instance of Struct A.
I want the only way for it to be created is as a return from the getStructA() method. Then the values can be accessed through the appropriate getters.
So is there any way to set a restrictions like that? So a Structure can't be instantiated outside of a certain class? Using C#, .Net4.0.
Thanks for your help.
---EDIT:----
To add some details on why am I trying to achieve this:
My class ABC has some "status" a person can query. This status has 2 string values and then a long list of integers.
There never will be a need to create an object/instance of "Status" by the programmer, the status can only be returned by "getStatus()" function of the class.
I do not want to split these 3 fields to different methods, as to obtain them I am calling Windows API (p/invoke) which returns similar struct with all 3 fields.
If I was indeed going to split it to 3 methods and not use the struct, I would have to either cache results or call the method from Windows API every time one of these 3 methods is called...
So I can either make a public struct and programmers can instantiate it if they want, which will be useless for them as there will be no methods which can accept it as a parameter. Or I can construct the library in such a way that this struct (or change it to a class if it makes things easier) can be obtained only as a return from the method.
If the "restricted" type is a struct, then no, there is no way to do that. The struct must be at least as public as the factory method, and if the struct is public then it can be constructed with its default constructor. However, you can do this:
public struct A
{
private string s;
private int i;
internal bool valid;
internal A(string s, int i)
{
this.s = s;
this.i = i;
this.valid = true;
}
...
and now you can have your library code check the "valid" flag. Instances of A can only be made either (1) by a method internal to your library that can call the internal constructor, or (2) by the default constructor. You can tell them apart with the valid flag.
A number of people have suggested using an interface, but that's a bit pointless; the whole point of using a struct is to get value type semantics and then you go boxing it into an interface. You might as well make it a class in the first place. If it is going to be a class then it is certainly possible to make a factory method; just make all the ctors of the class internal.
And of course I hope it goes without saying that none of this gear should be used to implement code that is resistant to attack by a fully-trusted user. Remember, this system is in place to protect good users from bad code, not good code from bad users. There is nothing whatsoever that stops fully trusted user code from calling whatever private methods they want in your library via reflection, or for that matter, altering the bits inside a struct with unsafe code.
Create a public interface and make the class private to the class invoking it.
public ISpecialReturnType
{
String SomeText{ get; }
int SomeValue{ get; }
}
class ABC{
public ISpecialReturnType getStructA(){
A a = //Get a value for a;
return a;
}
private struct A : ISpecialReturnType
{
private String _SomeText;
private int _SomeValue;
public A(String someText, int SomeValue) { /*.. set the initial values..*/ }
public String SomeText{ get { return _SomeText; } }
public int SomeValue{ get { return _SomeValue; } }
}
}
What exactly are you concerned about? A structure is fundamentally a collection of fields stuck together with duct tape. Since struct assignment copies all of the fields from one struct instance to another, outside the control of the struct type in question, structs have a very limited ability to enforce any sort of invariants, especially in multi-threaded code (unless a struct is exactly 1, 2, or 4 bytes, code that wants to create an instance which contains a mix of data copied from two different instances may do so pretty easily, and there's no way the struct can prevent it).
If you want to ensure that your methods will not accept any instances of a type other than those which your type has produced internally, you should use a class that either has only internal or private constructors. If you do that, you can be certain that you're getting the instances that you yourself produced.
EDIT
Based upon the revisions, I don't think the requested type of restriction is necessary or particularly helpful. It sounds like what's fundamentally desired to stick a bunch of values together and store them into a stuck-together group of variables held by the caller. If you declare a struct as simply:
public struct QueryResult {
public ExecutionDuration as Timespan;
public CompletionTime as DateTime;
public ReturnedMessage as String;
}
then a declaration:
QueryResult foo;
will effectively create three variables, named foo.ExecutionDuration, foo.CompletionTime, and foo.ReturnedMessage. The statement:
foo = queryPerformer.performQuery(...);
will set the values of those three variables according to the results of the function--essentially equivalent to:
{
var temp = queryPerformer.performQuery(...);
foo.ExecutionDuration = temp.ExecutionDuration
foo.CompletionTime = temp.CompletionTime;
foo.ReturnedMessage = temp.ReturnedMessage;
}
Nothing will prevent user code from doing whatever it wants with those three variables, but so what? If user code decides for whatever reason to say foo.ReturnedMessage = "George"; then foo.ReturnedMessage will equal George. The situation is really no different from if code had said:
int functionResult = doSomething();
and then later said functionResult = 43;. The behavior of functionResult, like any other variable, is to hold the last thing written to it. If the last thing written to it is the result of the last call to doSomething(), that's what it will hold. If the last thing written was something else, it will hold something else.
Note that a struct field, unlike a class field or a struct property, can only be changed either by writing to it, or by using a struct assignment statement to write all of the fields in one struct instance with the values in corresponding fields of another. From the consumer's perspective, a read-only struct property carries no such guarantee. A struct may happen to implement a property to behave that way, but without inspecting the code of the property there's no way to know whether the value it returns might be affected by some mutable object.
We are transfering our code from C++ to C# and due to limited knowledge of C# we are stuck into strange situation. Our problem is:
In c++ we have 2-3 types of class/structures which have pointers to property (std::string), purpose of pointer is to make sure that all the instance for similar object will point to same property. e.g
struct st1{
string strVal;
};
struct st2{
string* strVal;
};
//At time of creation
st1* objst1 = new st1();
st2* objst2 = new st2();
objst2.strVal = &objst1.strVal;
//After this at all point both object will point to same value.
I want this kind of architecture C#, I got some suggestion like:
Declare events
Make code unsafe and use pointers (but I think this will lead to some other problems)
Please let me know if something better and near to C++ can be done here..
In C# all clases are references / pointers. So as long as your property is of class type, you can have same instance in different structures.
But problem can arise when you use string. While it is class and reference property, it is enforced to be imutable. So when you change it, you dont change the instance itself, but you create new copy with those changes.
One solution that comes to mind is to create custom string class, that will simply contain string and use it as your type:
public class ReferenceString
{
public String Value { get; set; }
}
You could use a static property with inheritance:
class thing
{
static string stringThing;
public string StringThing
{
get { return stringThing; }
set { stringThing = value; }
}
}
class thing2 : thing
{
}
Then later:
thing theThing = new thing();
theThing.StringThing = "hello";
thing2 theThing2 = new thing2();
// theThing2.StringThing is "hello"
how can one use a Safearray to pass an array of custom types (a class containing only properties) from C++ to C#? Is using the VT_RECORD type the right way to do it?
I am trying in the following way, but SafeArrayPutElement returns an error when trying to fill the safearray the reference to the array of classes gets to the managed code as a NULL.
I have something like the following in the managed world:
[ComVisible(true)]
public interface IStatistics
{
double Mean { get; set; }
double StdDev { get; set; }
}
[Serializable]
[ComVisible(true)]
public class Statistics : IStatistics
{
public Mean { get; set; }
public double StdDev { get; set; }
}
Unmanaged world:
HRESULT hr = CoInitialize(NULL);
...
SAFEARRAY *pEquationsStatistics;
// common dimensions for all arrays
SAFEARRAYBOUND dimensions[1];
dimensions[0].cElements = 2;
dimensions[0].lLbound = 0;
pEquationsStatistics = SafeArrayCreate(VT_RECORD, 1, dimensions);
...
for (long i = 0; i < dimensions[0].cElements; i++)
{
long indices[1];
indices[0] = 0;
...
// Equation statistics
IStatisticsPtr pIStatistics(__uuidof(Statistics));
pIStatistics->PutMean(1.0); // so far so good
result = SafeArrayPutElement(pEquationsStatistics, indices, pIStatistics);
...
indices[0]++;
}
Please note that the I am able use the SafeArray to pass other arrays of BSTR with no problems between the two applications. So this is something peculiar to passing a structure.
Stefano
I'm not really sure if I understand your question right, but maybe you need VT_DISPATCH?
I think if you want it to work with VT_RECORD, then your struct should actually be a struct (not a class) and also needs the [StructLayout(LayoutKind.Sequential)] attribute.
Edit: Can it be that the error you first got was DISP_E_BADINDEX? What exactly is indices in your code? What does it contain? (You know that the signature of SafeArrayPutElement requires it to be a pointer, right?)