Hello,
We are starting to develop a 3D software to simulate the anatomic interior of a human being. The anatomical structures may vary their position, aspect and size from one 3D scenario ('person') to another.
We are trying to load that information into custom Blitz types reading it from a a database. Here is an example of our type 'Structure':
Type Estructura
Field estCod% ;code of the structure
Field estNom$ ;name of the structure
Field entEstX% ;x position
Field entEstY% ;y position
Field entEstZ% ;z position
Field entEstEsc% ;a custom scaling
Field m3dCod% ;the code of the respective 3d mesh
Field texCod% ;the code of the respective texture
Field modelo3d.Modelo3D ;the custom type holding the 3d mesh info
Field textura.Textura ;the custom type holding the texture info
End Type
For that purpose, we created an unmanaged dll written in C# to allow the communication between the blitz application and the database.
In the dll we have defined structs equivalent to the Blitz types. Here is the equivalent struct in C#:
public struct Estructura
{
public int estCod;
public string estNom;
public int entEstX;
public int entEstY;
public int entEstZ;
public int entEstEsc;
public int m3dCod;
public int texCod;
public Modelo3D modelo3d;
public Textura textura;
}
To fill the fields of the Blitz type, we instantiate one, set its code field (primary key at the DB) and then pass the type to a dll method (fillEstructura) that receives it by reference and sets every other field with the values obtained by querying the DB using the structure code.
Code in Blitz:
Global estructuras.Estructura[10]
Function traerEstructuras()
For i = 1 To 10
;10 is the number of structures to load (the codes in the DB are correlative, ranging from 1 to 10)
est.Estructura = new Estructura ;************
est\estCod = i
obtenerEstructura(est)
estructuras[i] = es
Next
End Function
Function obtenerEstructura(e.Estructura)
fillEstructura(e) ;here we call the method at the dll
e\estNom = getEstNom(e\estCod)
;sadly, in .NET, strings are not passed well within a referenced struct in an unmanaged environment (?)
;so we set it by calling a dll different function
e\modelo3D = New Modelo3D
e\modelo3d\m3dCod = e\m3dCod
obtenerModelo3D(e\modelo3d) ;similar to the present method for filling the 3D model custom type
e\textura = New Textura
e\textura\texCod = e\texCod
obtenerTextura(e\textura) ;similar to the present method for filling the texture custom type
End Function
Code in C# dll:
[ExportDllAttribute.ExportDll("fillEstructura", System.Runtime.InteropServices.CallingConvention.Cdecl)]
public static void fillEstructura(ref Estructura est)
{
string sql = "select * from Estructuras where EstCod=" + est.estCod;
//custom class and function to obtain get a Dataset containing the result of the sql query
DataSet ds = ManejadorBD.getInstance().executeQuery(sql);
if (ds.Tables[0].Rows.Count > 0)
{
DataRow fila = ds.Tables[0].Rows[0];
//fills the attributes of the struct with the proper values
est.entEstX = (int)fila["EntEstX"];
est.entEstY = (int)fila["EntEstY"];
est.entEstZ = (int)fila["EntEstZ"];
est.entEstEsc = (int)fila["EntEstEsc"];
est.texCod = (int)fila["TexCod"];
est.m3dCod = (int)fila["M3DCod"];
}
}
[ExportDllAttribute.ExportDll("getEstNom", System.Runtime.InteropServices.CallingConvention.Cdecl)]
public static string getEstNom(ref Estructura est)
{
string retorno = "";
string sql = "select EstNom from Estructuras where EstCod=" + est.estCod;
DataSet ds = ManejadorBD.getInstance().ejecutarQuery(sql);
if (ds.Tables[0].Rows.Count > 0)
{
DataRow fila = ds.Tables[0].Rows[0];
retorno = (string)fila["EstNom"];
}
return retorno;
}
Here are the respective entries at the .decls file:
.lib "Com.dll"
fillEstructura(est*): "fillEstructura"
getEstNom$(est*): "getEstNom"
Everything works fine on the individual tests, I mean when filling one structure at a time. However, when trying to batch process a lot of structures within a for or a while (like in the above blitz code example) the trouble begins: After every third loop of the for, the line marked with the ************ at the code (est.Estructura = new Estructura) generates a Memory Access Violation exception.
Why always after the third one? Why the first two always work fine no matter if you change the step of the for iteration to -1 to exclude an instance related issue? Why after every third time the line is executed and not before????
Please shed some light on this issue!
Thanks in advance for your help.
We are starting to develop a 3D software to simulate the anatomic interior of a human being. The anatomical structures may vary their position, aspect and size from one 3D scenario ('person') to another.
We are trying to load that information into custom Blitz types reading it from a a database. Here is an example of our type 'Structure':
Type Estructura
Field estCod% ;code of the structure
Field estNom$ ;name of the structure
Field entEstX% ;x position
Field entEstY% ;y position
Field entEstZ% ;z position
Field entEstEsc% ;a custom scaling
Field m3dCod% ;the code of the respective 3d mesh
Field texCod% ;the code of the respective texture
Field modelo3d.Modelo3D ;the custom type holding the 3d mesh info
Field textura.Textura ;the custom type holding the texture info
End Type
For that purpose, we created an unmanaged dll written in C# to allow the communication between the blitz application and the database.
In the dll we have defined structs equivalent to the Blitz types. Here is the equivalent struct in C#:
public struct Estructura
{
public int estCod;
public string estNom;
public int entEstX;
public int entEstY;
public int entEstZ;
public int entEstEsc;
public int m3dCod;
public int texCod;
public Modelo3D modelo3d;
public Textura textura;
}
To fill the fields of the Blitz type, we instantiate one, set its code field (primary key at the DB) and then pass the type to a dll method (fillEstructura) that receives it by reference and sets every other field with the values obtained by querying the DB using the structure code.
Code in Blitz:
Global estructuras.Estructura[10]
Function traerEstructuras()
For i = 1 To 10
;10 is the number of structures to load (the codes in the DB are correlative, ranging from 1 to 10)
est.Estructura = new Estructura ;************
est\estCod = i
obtenerEstructura(est)
estructuras[i] = es
Next
End Function
Function obtenerEstructura(e.Estructura)
fillEstructura(e) ;here we call the method at the dll
e\estNom = getEstNom(e\estCod)
;sadly, in .NET, strings are not passed well within a referenced struct in an unmanaged environment (?)
;so we set it by calling a dll different function
e\modelo3D = New Modelo3D
e\modelo3d\m3dCod = e\m3dCod
obtenerModelo3D(e\modelo3d) ;similar to the present method for filling the 3D model custom type
e\textura = New Textura
e\textura\texCod = e\texCod
obtenerTextura(e\textura) ;similar to the present method for filling the texture custom type
End Function
Code in C# dll:
[ExportDllAttribute.ExportDll("fillEstructura", System.Runtime.InteropServices.CallingConvention.Cdecl)]
public static void fillEstructura(ref Estructura est)
{
string sql = "select * from Estructuras where EstCod=" + est.estCod;
//custom class and function to obtain get a Dataset containing the result of the sql query
DataSet ds = ManejadorBD.getInstance().executeQuery(sql);
if (ds.Tables[0].Rows.Count > 0)
{
DataRow fila = ds.Tables[0].Rows[0];
//fills the attributes of the struct with the proper values
est.entEstX = (int)fila["EntEstX"];
est.entEstY = (int)fila["EntEstY"];
est.entEstZ = (int)fila["EntEstZ"];
est.entEstEsc = (int)fila["EntEstEsc"];
est.texCod = (int)fila["TexCod"];
est.m3dCod = (int)fila["M3DCod"];
}
}
[ExportDllAttribute.ExportDll("getEstNom", System.Runtime.InteropServices.CallingConvention.Cdecl)]
public static string getEstNom(ref Estructura est)
{
string retorno = "";
string sql = "select EstNom from Estructuras where EstCod=" + est.estCod;
DataSet ds = ManejadorBD.getInstance().ejecutarQuery(sql);
if (ds.Tables[0].Rows.Count > 0)
{
DataRow fila = ds.Tables[0].Rows[0];
retorno = (string)fila["EstNom"];
}
return retorno;
}
Here are the respective entries at the .decls file:
.lib "Com.dll"
fillEstructura(est*): "fillEstructura"
getEstNom$(est*): "getEstNom"
Everything works fine on the individual tests, I mean when filling one structure at a time. However, when trying to batch process a lot of structures within a for or a while (like in the above blitz code example) the trouble begins: After every third loop of the for, the line marked with the ************ at the code (est.Estructura = new Estructura) generates a Memory Access Violation exception.
Why always after the third one? Why the first two always work fine no matter if you change the step of the for iteration to -1 to exclude an instance related issue? Why after every third time the line is executed and not before????
Please shed some light on this issue!
Thanks in advance for your help.