Convert IFC EXPRESS schema entities/classes to VB.NET classes - vb.net

I'm working on an ifc project where I want to convert an EXPRESS file's classes into vb.net classes. It is really hard to process all the attributes of the stp file one by one, so I was wondering if there are alternative ways or tools which could convert the classes.
EDIT : I have discovered javatoolbox which does exactly what I want, but in java. I have also seen IFC Engine DLL but have not found any code available.

Creating classes for full EXPRESS schema is relatively complex task. If your language/platform of choice is vb.net I'd recommend to have a look on xBIM. It is open source toolkit which provides all you need to open IFC model and extract/create any data you need. xBIM is mostly written in C# so you can just reference it as a NuGet package. The latest development code also supports IFC4.

Both Jotne EPM www.epmtech.jotne.com and IFC Engine DLL www.ifcengine.com claim they support Visual Basic.

You can try out oipExpress. oipExpress is a early binding generator written in C++. Just implement our own generator that generates VB.Net classes. Currently, it just generates C++ classes.
A basic generator for VB.Net classes could look like this (the generated binding can be found also here):
class GeneratorVBNet : public Generator {
public:
GeneratorVBNet() {
}
virtual ~GeneratorVBNet() {
}
void generate(std::ostream &out, OpenInfraPlatform::ExpressBinding::Schema &schema) {
for (int i = 0; i < schema.getEntityCount(); i++) {
auto &entity = schema.getEntityByIndex(i);
std::stringstream ss;
ss << earlyBindingDestination << "\\" << entity.getName() << ".vb";
std::ofstream ofs(ss.str(), std::ofstream::out);
ofs << "Class " << entity.getName() << std::endl;
ofs << "End Class" << std::endl;
}
}
private:
std::string earlyBindingDestination = "E:\\dev\\EarlyBindingVBNet_IFC4x1_Add1";
};
The generated early binding will look like this:
The internal meta model of oipExpress looks like this:

Related

Does C++/WinRT provide mapping from enum symbol to string name?

I'm using C++/WinRT. The projection includes many enums. I find myself building my own table of enum values to string literals. This is not a big deal for enums with only a few defined values, but it's a pain when there are a lot of them.
What I really want is some form of compile-time or run-time reflection that converts an enum value into the string representation of the compile-time name that represents a given enum value. The code snippet below demonstrates. How can this be automated?
std::wostream& operator<< (
std::wostream& wout,
winrt::Windows::Graphics::DirectX::DirectXPixelFormat e)
{
// https://learn.microsoft.com/en-us/uwp/api/windows.graphics.directx.directxpixelformat
using winrt::Windows::Graphics::DirectX::DirectXPixelFormat;
switch (e) {
case DirectXPixelFormat::R8G8B8A8Int:
wout << L"R8G8B8A8Int";
break;
case DirectXPixelFormat::B8G8R8A8UIntNormalized:
wout << L"B8G8R8A8UIntNormalized";
break;
default:
// TODO: Many enums cases are missing.
// Find a way to compile-time-generate the string values from enum value.
wout << L"Unknown (" << std::to_wstring(static_cast<int32_t>(e)) << L")";
}
return wout;
}
I could build something that parses the winrt/*.h files to generate a header containing arrays of string literals, then #include the generated header. There probably exists sample code for doing this type of thing unrelated to C++/WinRT. But maybe C++/WinRT includes metadata in the SDK, which combined with one of the C++/WinRT command line tools, can easily do this for me? If it's there I have not found it.
I did find ApiInformation interface from winrt/Windows.Foundation.Metadata.h, as well as explanation of "Version Adaptive Code". I had hoped that OS COM interface behind ApiInformation has way to query a name for an enum value, but I was unable to find an answer there.
https://learn.microsoft.com/en-us/uwp/api/Windows.Foundation.Metadata.ApiInformation
how about this
https://learn.microsoft.com/en-us/windows/uwp/cpp-and-winrt-apis/move-to-winrt-from-cx#tostring
namespace winrt
{
hstring to_hstring(StatusEnum status)
{
switch (status)
{
case StatusEnum::Success: return L"Success";
case StatusEnum::AccessDenied: return L"AccessDenied";
case StatusEnum::DisabledByPolicy: return L"DisabledByPolicy";
default: return to_hstring(static_cast<int>(status));
}
}
}

Using custom DLL with Lua 5.1

I'm trying to use a custom DLL from within Lua. I have a simple DLL, for example, like
extern "C"
{
static int function_1(lua_State* L)
{
std::cout << "[DLL]this is a custom function" << std::endl;
lua_pushnumber(L, 10);
return 1;
}
__declspec(dllexport) int __cdecl luaopen_myDLL(lua_State* L)
{
L = luaL_newstate();
luaL_openlibs(L);
std::cout << "[DLL] being initialized!" << std::endl;
lua_register(L, "fun1", function_1);
luaL_dofile(L, "./run.lua");
return 1;
}
}
written in VS and built as dll.
After running within Lua
package.loadlib("./myDLL.dll", "luaopen_myDLL")()
or
require("myDLL")
the DLL is loaded and runs like expected and also runs the specified run.lua that execute function_1 just fine.
The run.lua has nothing special in it, just something like
f = function_1()
print("[Lua] Function_1 says", f, "\n");
My current issues now are:
I cannot run function_1() from the initial Lua script calling the DLL. Trying to do that I get
attempt to call global 'function_1' (a nil value)
i must use L = luaL_newstate(); inside my C code. For some reason, it doesn't work with the passed lua_State*, which I think is the reason why I cannot call the registered functions from the LUA script loading my DLL. Before running luaL_newstate() my lua_State has a valid address which doesn't change after the newstate.
I could theoretically run any Lua script from within my C library executing the registered functions, but this seems more like a dirty workaround to me.
My question now is if I'm missing something essential?
p.s.: I'm using Lua 5.1
The code below should work. It may not work because of the following reasons:
your binary you use to run initial Lua script (that has require("myDLL") in it) has a different Lua version and/or does not use shared dll.
your Lua headers you use in your C++ code have different Lua version from original lua.exe
you link your project against different Lua version
you compile Lua again with your solution (you must use only headers and already provided .lib file with Lua distribution, if you want to use lua.exe)
To make your code available in Lua you must use Lua headers for proper Lua version and link against proper .lib file and use lua.exe that uses shared library (lua.dll, I guess).
static int function_1(lua_State* L)
{
std::cout << "[DLL]this is a custom function" << std::endl;
lua_pushnumber(L, 10);
return 1;
}
extern "C" int __declspec(dllexport) luaopen_quik(lua_State *L) {
std::cout << "[DLL] being initialized!" << std::endl;
lua_register(L, "fun1", function_1);
luaL_dofile(L, "./run.lua");
return 0;
}
P. S. please provide your solution files so I can help further because it is not an issue with the code. -- it's the linkage issue.

CTest CDash: SubProject xml elements missing under Sites using include(CTest) only to submit test results

I built a source tree with several independent projects using CMake to build each individual project.
Important: I do NOT have a global CMakeLists.txt file to perform the whole build, I use generic scripts (windows (.cmd) and unix (.sh)) to loop on all subprojects. I want to keep projects independent and yet have the ability to build them all automatically.
In CDash on the other hand, I'd like to see all these independent projects as CDash subprojects as part of a bigger unique artificial CDash project.
To work with CDash, I followed the method described at:
http://www.cmake.org/Wiki/CMake/Testing_With_CTest
I'll name this method A.
Namely, I do:
enable_testing()
include(CTest)
And, then put some tests of my own.
Afterwards, I tried to follow following page indications to make my individual projects seen as subprojects:
http://www.kitware.com/media/html/CDashSubprojects.html
I'll name this method B.
The problem is that the xml that are submited to CDash lack the SubProject and Labels xml elements (tags for xml abusers), those under Sites, although my CMakeLists.txt (actually my CTestConfig.cmake) file has the following global property settings (I tried to put it in both files):
set_property(GLOBAL PROPERTY SubProject ${CMAKE_PROJECT_NAME})
set_property(GLOBAL PROPERTY Label ${CMAKE_PROJECT_NAME})
where CMAKE_PROJECT_NAME is -of course- well defined.
Do you know wjy SubProject and Labels elements are missing under Sites element of submited xml files?
Can methods A and B be mixed?
Furthermore, I checked CTest source, these global properties are added by this function (I took it from 2.8.10, couldn't download the source of 2.8.11 I'm using, so I hope there's no change it that otherwise sorry):
//----------------------------------------------------------------------
void cmCTest::AddSiteProperties(std::ostream& ostr)
{
cmCTestScriptHandler* ch =
static_cast<cmCTestScriptHandler*>(this->GetHandler("script"));
cmake* cm = ch->GetCMake();
// if no CMake then this is the old style script and props like
// this will not work anyway.
if(!cm)
{
return;
}
// This code should go when cdash is changed to use labels only
const char* subproject = cm->GetProperty("SubProject", cmProperty::GLOBAL);
if(subproject)
{
ostr << "<Subproject name=\"" << subproject << "\">\n";
const char* labels =
ch->GetCMake()->GetProperty("SubProjectLabels", cmProperty::GLOBAL);
if(labels)
{
ostr << " <Labels>\n";
std::string l = labels;
std::vector<std::string> args;
cmSystemTools::ExpandListArgument(l, args);
for(std::vector<std::string>::iterator i = args.begin();
i != args.end(); ++i)
{
ostr << " <Label>" << i->c_str() << "</Label>\n";
}
ostr << " </Labels>\n";
}
ostr << "</Subproject>\n";
}
// This code should stay when cdash only does label based sub-projects
const char* label = cm->GetProperty("Label", cmProperty::GLOBAL);
if(label)
{
ostr << "<Labels>\n";
ostr << " <Label>" << label << "</Label>\n";
ostr << "</Labels>\n";
}
}
Does ch->GetCMake() return NULL somehow in my case?
Thanks in advance for your help. Regards.
P.-S.: Please refrain yourself from asking me why I do this or that (unless you have a relevante point to make), because -one- it doesn't help, -two- if I do it, it's because I've got a good reason where this place is not a good one to expose it. I come here to seek your kind help preferably from someone who knows what s/he's talking about or a clear final "no it's not possible that way, do it that other way, because of this" (the because being mandatory - please no peremptory answers).

Exposing a managed COM local server - E_NOINTERFACE

Im trying to expose a local server that is written in C# to unmanaged code to allow interop! The managed code looks like that:
[Guid("A0D470AF-0618-40E9-8297-8C63BAF3F1C3")]
[ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IMyLocalInterface
{
void LogToServer(string message);
}
[Guid("9E9E5403-7993-49ED-BAFA-FD9A63A837E3")]
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
public class MyLocalClass : IMyLocalInterface
{
public MyLocalClass()
{
Console.WriteLine("Object created!");
}
public void LogToServer(string message)
{
Console.WriteLine("Log > " + message);
}
}
class Program
{
[MTAThread]
static void Main(string[] args)
{
var srv = new RegistrationServices();
var cookie = srv.RegisterTypeForComClients(typeof(MyLocalClass), RegistrationClassContext.LocalServer | RegistrationClassContext.RemoteServer, RegistrationConnectionType.MultipleUse);
Console.ReadLine();
srv.UnregisterTypeForComClients(cookie);
}
}
And my unmanaged code does the following:
#import "ManagedLocServer.tlb" no_namespace raw_interfaces_only
int _tmain(int argc, _TCHAR* argv[])
{
CoInitializeEx(NULL, COINIT_MULTITHREADED);
{
IMyLocalInterfacePtr ptr;
ptr.CreateInstance(__uuidof(MyLocalClass));
ptr->LogToServer(L"Initializing...");
}
CoUninitialize();
return 0;
}
After debugging ive seen that CoCreateInstance works without any problems, that means "Object created" is printed into the managed servers console. But then QueryInterface on that object fails with E_NOINTERFACE. Im a bit confused why this happens. Is it a problem with registration (i only have a LocalServer32 entry for my CLSID)? Is it a problem within my managed code? Would be nice if someone could give me a hint :)
Greetings
Joe
You are using out-of-process COM. That requires marshaling support, to make a method call the arguments of the method need to be serialized. That's normally done by building the proxy/stub DLL from the code generated by midl.exe from the .idl file. Or by using the standard marshaller which works with the type library. Both require registry entries in HKCR\Interface
You get the E_NOINTERFACE because COM cannot find a marshaller. This is trivial to solve if you have an .idl file but you don't, the server is implemented in .NET. No idea how to solve this, I never tried to make this work. A remote possibility is that the CLR interop layer provides marshaling support. But you'd surely at least have to use ComInterfaceType.InterfaceIsDual. This is just a guess. If I tried to make this work, I'd start from an .idl first.

using activex dll in vc++ win32 project

i have got a ScreenCameraSDK and it comes with a 11kb dll file, it has a documentation too which lists the functions which can be used. It says
ScreenCamera SDK ActiveX Reference Documentation
ActiveX Reference
The ActiveX ID on the system is: ScreenCameraSDK.RemoteControl
Every method on the interface returns FAIL or SUCCESS. (0 or 1).
Create an instance of the ActiveX on your application, and then call InitializeScreenCameraRemoteControl. If the return value is SUCCESS then ScreenCamera is properly installed and you can then call any other method on the ActiveX's interface. If not ScreenCamera could not be found and you should contact support.**
Now my question is, i have the dll and no other files. How can i use the functions inside it in a VC++ Project with Visual Studio 2008.
Thanks
I TRIED THE FOLLOWING CODE BUT GOT COMPILATION ERROR OF UNDEFINED IDENTIFIER
#include <stdio.h>
// This is the path for your DLL.
// Make sure that you specify the exact path.
#import "e:\ScreenCameraSDK.dll" no_namespace
void main()
{
BSTR bstrDesc;
try
{
CoInitialize(NULL);
short st = 2;
short st1;
// Declare the Interface Pointer for your Visual Basic object. Here,
// _Class1Ptr is the Smart pointer wrapper class representing the
// default interface of the Visual Basic object.
_Class1Ptr ptr;
// Create an instance of your Visual Basic object, here
// __uuidof(Class1) gets the CLSID of your Visual Basic object.
ptr.CreateInstance(__uuidof(Class1));
st1 = ptr->MyVBFunction(&st);
}
catch(_com_error &e)
{
bstrDesc = e.Description();
}
CoUninitialize();
}
it says _Class1Ptr is unknown!
BSTR bstrDesc;
try
{
HRESULT hr= CoInitialize(NULL);
CLSID clsid;
hr = CLSIDFromProgID(OLESTR("<complete class name as see in registry>"),&clsid);
short st = 2;
short st1;
//nameOfClassInOCX is placeholder for explanation. If you OCX com class name is blabla
//use _blabla and so on.
_nameOfClassInOCX * ptr;
hr = CoCreateInstance(clsid,NULL,CLSCTX_INPROC_SERVER,__uuidof(_nameOfClassInOCX ),(LPVOID*)&ptr);
cout << ptr->GetFees("hi") <<endl;
ptr->Release();
}
catch(_com_error &e)
{
bstrDesc = e.Description();
}
CoUninitialize();
First of all you have to do this is #import the dll, and the compiler will automatically generate all required definitions from it. Then create objects from the library by using either smart pointers, or CreateInstance().
#import "C:\files\test.dll" no_namespace rename("EOF", "EOFile")
...
int main() {
if (FAILED(::CoInitialize(NULL)))
return 0;
........
::CoUninitialize();
return 0;
}