Marshalling arrays of structures in VB.NET - vb.net

I have a third-party C DLL that I am trying to call from VB.NET.
The API has in and out structures that are multi-level. For the sake of brevity:
typedef struct
{
int nObjectID;
char szObjectType[128];
int nConfidence;
int nAction;
DH_RECT BoundingBox;
DH_POINT Center;
int nPolygonNum;
DH_POINT Contour[DH_MAX_POLYGON_NUM];
DWORD rgbaMainColor;
<snip>
}
refers to two other structures (DH_RECT & DH_POINT). These are defined as:
typedef struct
{
long left;
long top;
long right;
long bottom;
} DH_RECT, *LPDH_RECT;
typedef struct
{
short nx;
short ny;
} DH_POINT, *LPDH_POINT, NET_POINT, *LPNET_POINT;
In my VB.NET version, I used this:
<StructLayout(LayoutKind.Sequential, Pack:=1)>
Public Structure DH_RECT
Public left As Int32
Public top As Int32
Public right As Int32
Public bottom As Int32
End Structure
<StructLayout(LayoutKind.Sequential, Pack:=1)>
Public Structure DH_POINT
Public nx As Int16
Public ny As Int16
End Structure
<StructLayout(LayoutKind.Sequential, Pack:=4)>
Public Structure DH_MSG_OBJECT
Public nObjectID As Int32
<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=128)>
Public szObjectType As String
Public nConfidence As Int32
Public nAction As Int32
Public BoundingBox As DH_RECT
Public Center As DH_POINT
Public nPolygonNum As Int32
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=16)>
Public Contour() As DH_POINT
Public rgbaMainColor As UInt32
<snip>
After calling the DLL function and moving the result into the structure using Marshal.PtrToStructure, everything after nPolygonNum is 0 or garbage. Mostly 0.
I suspect the error to be in the declaration for Contour. This is supposed to be an array of 16 of the type structure DH_POINT. I think the declaration should not be <MarshalAs(UnmanagedType.ByValArray, SizeConst:=16)> but can't get any other type to work.

Related

How works extensions method in VB.net with an interface as a object

I am struggling with an extension method in VB.NET, but I can't find why I can't implement this (I came from C# and I still having issues like this between language specification and how the language works, sorry if this question is too newbie):
namespace FakeBusiness.BusinessInterface
{
public interface IBusiness
{
int Id { get; set; }
string Name { get; set; }
}
}
namespace FakeBusiness.SharedExtensions
{
using FakeBusiness.BusinessInterface;
public static class ExtensionsMethods
{
public static bool IsEmpty(this IBusiness theObject)
{
return theObject != null && theObject.Id != 0;
}
}
}
namespace FakeBusiness.BusinessLogic
{
using FakeBusiness.BusinessInterface;
using FakeBusiness.SharedExtensions;
public class Business : IBusiness
{
public int Id { get; set; }
public String Name { get; set; }
}
public static class Program
{
public static void Main(string[] args)
{
IBusiness obj = new Business();
Console.WriteLine($"The object is: {(obj.IsEmpty() ? "empty" : "not empty")}");
}
}
}
And I want to achieve the same logic but for a reason VB.NET says 'Cannot resolve the symbol' even if I import explicitly the namespace from the extension method:
Namespace FakeBusiness.SharedExtensions {
<Extension()>
Public Function IsBusinessObjectEmtpy(ByVal business As IBusiness) As Boolean
Return (business IsNot Nothing AndAlso business.Id = 0)
End Function
End Namespace
Namespace FakeBusiness.BusinessLogic
Public Class BusinessObject : Implements IBusiness
Property Id As Integer Implements IBusiness.Id
Property Name As String Implements IBusiness.Name
Public Sub New()
End Sub
End Class
Public Interface IBusiness
Property Id As Integer
Property Name As String
End Interface
Public Class FakeBusiness.SomeLogic
Public Sub SomeLogic()
Dim newObject = New BusinessObject()
If newObject.IsBusinessObjectEmpty() Then
' Do something...
End If
End Sub
End Class
End Namespace
Also I read that a possible solution is to use the instructions Option Strict On/Off and also Option Infer On/Off.
I tried every possible combination between these pair of compiler instructions but it didn't work.
Anyone knows how to fix this issue with an extension method?
Another possible solution is to put the same method into a base class and implement with an interface, but I want to achieve this in this way
because it will be useful to use in every class if I use a TypeParameter in the extension method.
Any suggestion?
In a Console Application project with a root namespace of FakeBusiness, the following is the direct equivalent of that C# code:
Namespace BusinessInterface
Public Interface IBusiness
Property Id As Integer
Property Name As String
End Interface
End Namespace
Imports System.Runtime.CompilerServices
Imports FakeBusiness.BusinessInterface
Namespace SharedExtensions
Public Module ExtensionMethods
<Extension>
Public Function IsEmpty(theObject As IBusiness) As Boolean
Return theObject IsNot Nothing AndAlso theObject.Id <> 0
End Function
End Module
End Namespace
Imports FakeBusiness.BusinessInterface
Imports FakeBusiness.SharedExtensions
Namespace BusinessLogic
Public Class Business
Implements IBusiness
Public Property Id As Integer Implements IBusiness.Id
Public Property Name As String Implements IBusiness.Name
End Class
Module Program
Sub Main(args As String())
Dim obj As IBusiness = New Business()
Console.WriteLine($"The object is: {If(obj.IsEmpty(), "empty", "Not empty")}")
End Sub
End Module
End Namespace

Can you make anonymous classes in vb.net?

I'd like to do this in vb.net (c++ code)
struct Banana {
struct {
int width;
int height;
} Physical;
std::string name;
};
It basically serves to categorize the fields so I can go Banana.Physical.width. Now, I know I could technically do it like this
Public Class Banana
Public name As String
Public Physical As New PhysicalClass
Public Class PhysicalClass
Public width As Integer
Public height As Integer
End Class
End Class
But I was hoping maybe there is some syntax candy around so I wouldn't have to name the PhysicalClass that I would never use anywhere else anyways.

Design: classes with same implementation but different method names

I have multiple classes that have similar implementation for different named methods:
class MyClassX
{
public int MyClassXIntMethod(){}
public string MyClassXStringMethod(){}
}
class MyClassY
{
public int MyClassYIntMethod(){}
public string MyClassYStringMethod(){}
}
the methods inside the classes have similar implementation but because the method's names are different (due to 3rd party constraints) i cannot use inheritance.
I'm looking for an elegant solution that would be better than implementing the same functionality over and over again.
The classic answer IMHO is use the adpater pattern for every 3rd party calling party.
Don't apply blindly but see if it is a good fit first.
class MyClassXAdapter
{
IMyInterface _myImpClass
public int MyClassXIntMethod(){ return _myImpClass.IntMethod()}
public string MyClassXStringMethod(){ return _myImpClass.StringMethod() }
}
class MyClassYAdapter
{
IMyInterface _myImpClass
public int MyClassYIntMethod(){ return _myImpClass.IntMethod()}
public string MyClassYStringMethod(){ _myImpClass.StringMethod() }
}
class MyClassImplementation :IMyInterface
{
public int IntMethod(){}
public string StringMethod(){}
}
And whats the problem in using composition?
class MyClassY
{
private MyClassX myclx;
public int MyClassYIntMethod()
{
return myclx.MyClassXIntMethod();
}
public string MyClassYStringMethod(){...Similarly here...}
}
Why not simply create a common super class, and let each "MyClass_" call that common function? You can have a different program signature and still reuse the same codes pieces. Without copy and paste the same code again.
class MyClassX extends MyClassGeneric
{
public int MyClassXIntMethod(){}
public string MyClassXStringMethod(){}
}
class MyClassY extends MyClassGeneric
{
public int MyClassYIntMethod(){ return MyClassIntMethod();}
public string MyClassYStringMethod(){return MyClassStringMethod();}
}
class MyClassGeneric
{
protected int MyClassIntMethod(){ /*...... logic .....*/ return 0; }
protected string MyClassStringMethod(){/*...... logic ....*/return "";}
}
Real world example.
Without "software patternitis". (I apply software patterns, very useful, but, I'm not adicted to them).
collections.hpp
#define pointer void*
class Collection {
protected:
VIRTUAL bool isEmpty();
VIRTUAL void Clear();
}
class ArrayBasedCollection: public Collection {
protected:
int internalInsertFirst(pointer Item);
int internalInsertLast(pointer Item);
pointer internalExtractFirst(int Index);
pointer internalExtractLast(int Index);
}
class Stack: public ArrayBasedCollection {
public:
OVERLOADED bool isEmpty();
OVERLOADED void Clear();
// calls protected "internalInsertFirt"
void Push(pointer Item);
// calls protected "internalExtractLast"
pointer Pop(pointer Item);
}
class Queue: public ArrayBasedCollection {
public:
OVERLOADED bool isEmpty();
OVERLOADED void Clear();
// calls protected "internalInsertFirt"
void Push(pointer Item);
// calls protected "internalExtractFirst"
pointer Pop(pointer Item);
}
Cheers.

Passing an array of interfaces from C# to C++/CLI

I am trying to pass an array of interfaces from C# to C++/CLI. Here is the code:
// *** SafeArrayTesting_PlusPlus.cpp ***
#include "stdafx.h"
#include <comdef.h>
using namespace System;
using namespace System::Runtime::InteropServices;
namespace SafeArrayTesting_PlusPlus {
public ref class MyCppClass
{
public:
MyCppClass();
~MyCppClass();
void SetMyInterfaces(
array<SafeArrayTesting_Sharp::MyInterface^>^ myInterfaces);
};
MyCppClass::MyCppClass(){}
MyCppClass::~MyCppClass(){}
void MyCppClass::SetMyInterfaces(array<SafeArrayTesting_Sharp::MyInterface^>^
myInterfaces)
{
// Create safearray
SAFEARRAY *safeArrayPointer;
SAFEARRAYBOUND arrayDim[1]; // one dimensional array
arrayDim[0].lLbound= 0;
arrayDim[0].cElements= myInterfaces->Length;
safeArrayPointer = SafeArrayCreate(VT_UNKNOWN,1,arrayDim);
// copy ints to safearray
for (long lo= 0;lo<myInterfaces->Length;lo++)
{
IntPtr myIntPtr = Marshal::GetIUnknkownForObject(myInterfaces[lo]);
SafeArrayPutElement(
safeArrayPointer,
&lo,
static_cast<void*>(myIntPtr)
);
}
// do something with the safearray here - area XX
}}
// *** SafeArrayTesting_Main.cs ***
using SafeArrayTesting_PlusPlus;
using SafeArrayTesting_Sharp;
namespace SafeArrayTesting_Main
{
class SafeArrayTesting_Main
{
static void Main()
{
var myCppClass = new MyCppClass();
MyInterface myInterface = new MyClass();
myCppClass.SetMyInterfaces(new[]{ myInterface });
}
}}
// *** SafeArrayTesting_Sharp.cs ***
using System;
using System.Runtime.InteropServices;
namespace SafeArrayTesting_Sharp
{
[ComVisible(true)]
public interface MyInterface
{
int MyInt { get; set; }
string MyString { get; set; }
DateTime MyDateTime { get; set; }
}
[ComVisible(true)]
public class MyClass : MyInterface
{
public int MyInt{get;set;}
public string MyString{get;set;}
public DateTime MyDateTime{get; set;}
}
// Just to please the compiler; bear with me.
class DummyClass { static void Main() { } }
}
As written here, the code runs and compiles cleanly. However, when running the "area XX" part, I get a System.Runtime.InteropServices.SEHException.
The XX code is just a single line which calls an auto-generated method accepting a SAFEARRAY pointer. Here is the declaration of this method (from a .tlh file):
virtual HRESULT __stdcall put_SafeArray (
/*[in]*/ SAFEARRAY * pRetVal ) = 0;
I actually think this method converts the SAFEARRAY back to a .NET array - it's all part of a conversion project my company is running at the time. So there is no alternative to using a SAFEARRAY.
Anyway, it would really surprise me if the code without the XX part is bug-free; I'm quite a novice when it comes to C++. Can you help me spot some of the problems? If anyone can suggest a better way of testing the validity of the SAFEARRAY that would also be a help.
(By the way, this is a more complex variation of the question SafeArrayPutElement method throws System.AccessViolationException , in which I was just passing an array of ints from C# to C++/CLI.)
Several problems. For one, you don't actually store a VARIANT in the array. This is ultimately not going anywhere, a SafeArray cannot store references to managed objects. The garbage collector moves objects around, it cannot see references held by unmanaged code so it cannot update the reference.
At best, you could create an array of VT_UNKNOWN or VT_DISPATCH. But you can't get the COM interface pointer for these managed objects, they are not [ComVisible]. When you fix that, you'd use Marshal.GetIDispatchForObject() or Marshal.GetIUnknownForObject() to get the interface pointer to store in the array.

Private or Protected Set for a MustOverride Property

I'd like to have a Private or Protected "Setter" for a property that also happens to be an abstract (MustOverride). I'm porting some code from C# to VB and in C# this is pretty straight forward. In VB not so much (for me anyway).
Some code...
In C#...
public abstract class BaseClassWithAnAbstractProperty
{
public abstract int AnAbstractIntegerProperty { get; protected set; }
}
public class Foo : BaseClassWithAnAbstractProperty
{
private int _anAbstractIntegerPropertyField = 0;
public override int AnAbstractIntegerProperty
{
get { return _anAbstractIntegerPropertyField; }
protected set { _anAbstractIntegerPropertyField = value; }
}
}
In VB...
Public MustInherit Class BaseClassWithAnAbstractProperty
Public MustOverride Property AnAbstractIntegerProperty() As Integer
End Class
Public Class Foo
Inherits BaseClassWithAnAbstractProperty
Private _anAbstractIntegerPropertyField As Integer
Public Overrides Property AnAbstractIntegerProperty As Integer
Get
Return _anAbstractIntegerPropertyField
End Get
Protected Set(ByVal value As Integer)
_anAbstractIntegerPropertyField = value
End Set
End Property
End Class
The issue seems to be the inability to flesh-out the Get/Set specifics in the declaration.
Am I chasing a ghost?
For the record, the closest VB translation would give you:
Public MustInherit Class BaseClassWithAnAbstractProperty
Public ReadOnly MustOverride Property AnAbstractIntegerProperty() As Integer
End Class
This might work, but as I found out, VB doesn't support this for Interfaces, at least