I am creating an interpreter from IL (A compiled C#\VB code) to C. I tried to create extern property when I interpret it I'll set my own code.
For an example:
struct String {
public extern override ValueType Clone( ); //Works but with some warnings.
public char this[ int index ] {
extern get;
//'System.String.this[int].get' must declare a body because it is not marked abstract, extern, or partial
//The modifier 'extern' is not valid for this item
extern set; //Didn't work either.
}
}
How I can make getters and setters without body? (BTW I can't mark it as abstract too without getting errors.)
I know this question isn't useful. But very to me.
I think you want to suggest your interpretator to use alternative implemetation (instead of IL use your custom code). Most CLR friendly way would be to create attribute that your interpreter will read and correspondingly use some of your own code, sort of reverse PInvoke.
struct MyString {
[WhenRunningInInterpretator(implementationFunction="function42")]
public char this[ int index ] {
get {...} set {....}; }
}
Related
i tried to test the examples from the website but the second one won't work.. i need to create instances and call the methods from the class where the instance is from. The first example is explained here.
It seems I don't get the right python code :/ to reach the method and attribute behind pointer object..
This is the c# dll
[ComVisible(true)]
[Guid("0000000a-000b-000c-0001-020304050607"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ISample
{
// without MarshalAs(UnmanagedType.BStr), .Net will marshal these strings as single-byte Ansi!
// BStr is equivalent to Delphi's WideString
String Name
{
// this is how to add attributes to a getter's result parameter
[return: MarshalAs(UnmanagedType.BStr)]
get;
// this is how to add attributes to a setter's value parameter
[param: MarshalAs(UnmanagedType.BStr)]
set;
}
int DoSomething(int value);
}
public class Sample : ISample
{
public String Name{ get; set; }
public int DoSomething(int value)
{
return value + 1;
}
}
static class Exports
{
[DllExport]
public static void CreateSampleInstance([MarshalAs(UnmanagedType.Interface)]out ISample instance)
{
instance = new Sample{ Name = "Test" };
}
}`enter code here`
i tried in python shell
>>>import ctypes
>>>a=ctypes.cdll.LoadLibrary(source)
>>>b=a.CreateSampleInstance
>>>b
<_FuncPtr object at 0x028E65D0>
>>>b.Name
Traceback (most recent call last):
File "<pyshell#85>", line 1, in <module>
instance.Name
AttributeError: '_FuncPtr' object has no attribute 'Name'
Sure the pointer can't know the method DoSomething and the attribute Name, but how i can reach them :/
I'd recommend you take a look a IronPython (http://ironpython.net/) and specifically take a look at http://ironpython.net/documentation/dotnet/dotnet.html#id31
I have this code in C# but I have a problem whit this code:
struct myStruct
{
public string sOne;
public string sTwo;
}
public static int ChangeStruct(out myStruct[] arrmyStruct)
{
arrmyStruct= new myStruct[256];
arrSNChildrenStruct[0].sOne= "";
arrSNChildrenStruct[0].sTwo= "";
return 0;
}
But when I build, I have this error:
Inconsistent accessibility: parameter type 'out ........ is less accessible than method .....
What's wrong?
Thanks
Make a public struct myStruct instead of internal struct. Or make ChangeStruct() private if you only use it locally.
This has nothing to do with it being an out parameter, or an array. You'd get the same error with:
public static void ChangeStruct(myStruct foo)
Your method is public, but your struct is internal (the default accessibility for any top-level type) or private if it's a nested type. That means that any caller external to your assembly should have access to the method... but can't possibly understand the method signature. C# doesn't allow you to declare methods which refer to types which can't be seen by all possible callers.
Options:
Make the method internal or private
Make the struct public
Other notes:
Your naming is very unconventional. Name your types according to their meaning, and make it PascalCased. Drop the "arr" prefix from your variable names.
Public fields are usually a bad idea, as are mutable structs.
I have a C# library that I'm trying to expose to VBA. I can pass parameters to functions just fine (ie "ref byte[] someArray"), but passing objects or structs just won't work.
If I try passing a byte array as a property of a class, I get the following error in VB-
Function or interface marked as restricted, or the function uses an Automation type not supported in Visual Basic
If I try passing a byte array as a property of a struct, I get the following error in VB-
I've been fighting this for two days now and while I keep finding posts that claim to have the answer, none of them have worked for me.
So here's my code as it currently sits:
[ComVisible(true)]
[Guid("7F53F7A5-15C9-4A99-A855-38F5E87702D0")]
[InterfaceType(ComInterfaceType.InterfaceIsDual)] // Tried as InterfaceIsDual and as InterfaceIsIDispatch
public interface IDetail
{
[DispId(1)] // Tried with and without these
int SomeInt { get; set; }
[DispId(2)]
string SomeString { get; set; }
[DispId(3)]
byte[] SomeByteArray {
return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_UI1)]
get;
[param: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_UI1)]
set;
}
}
[ComVisible(true)]
[Guid("F77FB3D4-27E0-4BFA-A21E-5ACB671151E9")]
[ClassInterface(ClassInterfaceType.None)]
[ProgId("G4COMTest.Detail")]
public class Detail:IDetail
{
public int SomeInt { get;set; }
public string SomeString { get; set; }
// Tried MarshalAs in all combinations of class and interface
public byte[] SomeByteArray {
[return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_UI1)]
get;
[param: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_UI1)]
set;
}
}
[ComVisible(true)]
[Guid("5E8F9FF0-3156-479E-A91D-0DADD43881FB")]
[ClassInterface(ClassInterfaceType.None)]
public class Worker:IWorker
{
// works with the 'ref'
public int ReturnIntWByteArrayParam(ref byte[] testByteArray)
{
return testByteArray.Count();
}
public int ReturnIntWObjParam(IDetail detail)
{
return detail.SomeInt;
}
public IDetail ReturnObjNoParams()
{
var o = new Detail();
o.SomeInt = 87;
o.SomeString = "What are you doing Dave";
return o;
}
}
[ComVisible(true)]
[Guid("04962F29-DBBD-48AC-B4FB-180EEF562771")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface IWorker
{
int ReturnIntWByteArrayParam(ref byte[] testByteArray);
int ReturnIntWObjParam(IDetail detail);
IDetail ReturnObjNoParams();
}
Calling it from VB6:
Dim o As New G4COMTest.Worker
Dim d As New G4COMTest.Detail
Dim byt(2) As Byte
d.SomeInt = 356 '// Works
d.SomeString = "Hello from client" '// Works
d.SomeByteArray = byt '// Errors as either class or struct
MsgBox mWorker.ReturnIntWObjParam(d)
Thanks in advance for any help!
The C# array property exposes a getter and a setter to COM exactly as you would expect it to (the MarshalAs attribute is unnecessary, the marshaler does detect it correctly by default).
The problem is that the setter, like all property setters in .NET, passes the value parameter by value. Unfortunately, VBA does not support passing arrays by value. It's a fundamental limitation of the language that's been there since day one. Even more unfortunately, COM interop does not provide any way to override this behaviour with attributes. You have two choices:
A - Define your own setter method and call it from VBA instead of the property setter, e.g.
void SetSomeByteArray(ref byte[] value) { SomeByteArray = value; }
B - Change the property type to object and use variant arrays instead of strongly-typed arrays.
PS: Be careful with string properties too. These normally work just fine, but if you pass a null string value to VBA, it will error because the VBA String type can't store null references.
In your code class Detail has the ClassInterfaceType set to None, if you set it to AutoDispatch the code you have should work. From MSDN:
Using the class interface is an acceptable option for scripted clients, Microsoft Visual Basic 6.0 clients, or any late-bound client that does not cache the DispIds of interface members."
http://msdn.microsoft.com/en-us/library/4fcadw4a(v=vs.110).aspx
Since the client you are calling from is VB6 - you can set the ClassInterfaceType to AutoDispatch or even omit it (as default is AutoDispatch). This will generate only the Dispatch only class interface and not include any members from the interface. When calling from VB6, assigning an array directly to a property should work as it uses IDispatch Invoke function (late binding).
We tested this with a string array and it works.
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.
I am calling into a native dll from C#. For the specific function in question, one of the parameters I need is a structure which contains a doubly-indirect field (pointer to a pointer).
For example, take the following C prototype and structs:
int someFunc(SomeStruct* result);
struct SomeStruct
{
DWORD foo;
AnotherStruct** ppResultStruct;
}
struct AnotherStruct
{
DWORD bar;
}
The following C# code provides only a single level of indirection for the field AnotherStruct, which is incorrect:
[DllImport("my.dll")]
public static extern int someFunc(SomeClass result);
[StructLayout(LayoutKind.Sequential)
public class SomeClass
{
int foo;
AnotherClass resultClass;
}
[StructLayout(LayoutKind.Sequential)]
public class AnotherClass
{
int bar;
}
How can I achieve the double-indirection that's required here? I know how to do it in the case of a doubly-indirect parameter to a function, but I'm confused by the fact that it's embedded in a struct.
Maybe I should declare the AnotherClass field as an IntPtr, and then resort to unsafe code to assign it an appropriate value. Is that a valid approach, and are there any other/better options?
Without a custom marashaler you cannot build a class that both contains a standard inline struct definition and double indirection. This type of marshaling requires a bit of magic to achieve.
The best way to approach this is to treat the double indirection as a pointer which it actual is. Then use a pretty property to take care of the evilness
[StructLayout(LayoutKind.Sequential)
public class SomeClass
{
int foo;
IntPtr resultPtr;
AnotherStruct resultStruct {
get {
var temp = (IntPtr)Marshal.PtrToStructure(resultPtr, typeof(IntPtr));
return (AnotherStruct)Marshal.PtrToStructure(temp, typeof(AnotherStruct));
}
}
}
[StructLayout(LayoutKind.Sequential)]
public class AnotherStruct
{
int bar;
}