VB.NET framework question

Mummy

Regular
Hello,

im sorry if this thread is barely on topic, im writing an editor for my engine in VB.NET but the problem is not in the 3d department :oops:

Let me explain the situation, i have the engine core done in a C++ DLL, the DLL exports many functions which work very well when called from the VB.NET application. Everything works fine, marshalling structures, floats, integers etc, the editor stays up for days rendering and operating, the application seems stable.

I've added an export function which is expected to fill an array of structures defined both VB and in C++ with vertex and pixel shaders information, each element of the array is a vertex or a pixel shader information structure. The VB.NET application creates the array and passes it to the dll function, the dll function fills the array and then returns the number of shaders it has loaded so far. The problem is, AFTER i call the DLL function (which is called DllEnumeraShaders() ) the size of the VB.NET array, which is defined as 512 in the VB.NET application, is truncated to 1(0), no matter what i do in the C++ DLL (so im sure it's a marshalling problem).

Here is the code:

Dim InfoArray(512) As InfoShader
Dim ret As Integer

ret = DllEnumeraShaders(InfoArray, InfoArray.Length, eTipoShader.IS_VERTEXSHADER)

this is the function def in vb net:

Public Declare Auto Function DllEnumeraShaders Lib "DLLEngine" Alias "_116" (<MarshalAs(UnmanagedType.LPArray)> ByRef array() As InfoShader, <MarshalAs(UnmanagedType.I4)> ByVal lunghezzamax As Integer, <MarshalAs(UnmanagedType.I4)> ByVal TipoShader As eTipoShader) As Integer

this is the InfoShader structure (which is expected to grow as soon i've fixed this):

<StructLayout(LayoutKind.Sequential)> _
Public Structure InfoShader
<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=512)> Public NomeFile As String
Public RefCount As Integer
End Structure

this is the C++ DLL function:

// DllEnumeraShaders
int DLLENGINE_API _116(Dispositivo::InfoShader **info, int arraylen, int type)
{
// Even by doing nothing the array gets truncated
return 3;

if (Engine == 0) {
g_LogClass.ScriviFileDiLog("DllEnumeraShaders() Engine non inizializzato", E_ERRORE, V_SEMPRE);
return 0;
}

return Engine->EnumeraShaders(info, arraylen, type);
}

Im getting quite mad, i can't seem to figure out what im doing wrong... any ideas?
 
just me thinking aloud


<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=512)> Public NomeFile As String
Public RefCount As Integer

could it be down to the differnces in how the 2 languages store strings

eg: some lanuages know its the end of the string because of the null terminator
while vb may store strings like pascal with the length of the string as the first char ?

just a thought im sure someone cleverer will come up with a better one ;)



edit: after deciding to read your post properly instead of jumping in with the first thing that entered my brain just realised how daft the above answer is....
so
could it be that the dll is only being passed the first element of the array
 
Last edited by a moderator:
Its not about the string davros, it's the array size, the string works fine.
InfoArray(512) becomes InfoArray(1) after i call the dll function, every if the dll function is not doing anything (notice the return 3 in the c++ function).

Digitalwanderer said:
It seems to be missing an awful lot of noms and sups

Well, for noms we need farhan which will happily help :) and for sups we have you, so we are fine.

Dig.
 
Last edited by a moderator:
This is probably a noobish question, but in my many years of vb.net usage I have never had to define a dll's function like you did. The only time that I did have to was back when I was using vb 6.0 or older, for instance to access win32 calls. Can't you just properly reference the dll and have vb.net generate an interop for you? If there are any type conversion errors in your code right now, that could take care of them.
The other mistake I tend to make, but that's probably got nothing to do with this, is that when you use a pointer to an object (or an array?) byval and byref aren't quite what you'd expect them to be compared to what they do when you pass a regular string value. I'm terribly unsure if that's got anything to do with this at the moment (my brain's off after the weekend, may try again later this week ;) ) but maybe these suggestions trigger something in your own brain. ;)
 
Ahh, i think i figured it out. Seems like arrays have to be passed by value anyway.. which is kinda weird, anyway this:

Public Declare Auto Function DllEnumeraShaders Lib "DLLEngine" Alias "_116" (<MarshalAs(UnmanagedType.LPArray)> <[In](), Out()>ByVal info() As InfoShader, <MarshalAs(UnmanagedType.I4)> ByVal lunghezzamax As Integer, <MarshalAs(UnmanagedType.I4)> ByVal TipoShader As eTipoShader) As Integer

seems to work. The bolded part is fundamental,im not really sure what those mean, except for the fact that the array is both passed and returned, in a way, by the function.

In the c++ code i modified the function this way:

int DLLENGINE_API _116(Dispositivo::InfoShader *info, int lungmax, int tipo)
{
if (Engine == 0) {
g_LogClass.ScriviFileDiLog("DllEnumeraShaders() Engine non inizializzato", E_ERRORE, V_SEMPRE);
return 0;
}

return Engine->EnumeraShaders(info, lungmax, tipo);
}

InfoShader *info replaced InfoShader **info, because the array is passed by value.
 
Back
Top