Close

Relief for ODA Team in Ukraine

Learn more
ODA Drawings SDK
Using Drawings SDK Debug Macros

Debug macros help users perform many useful things during compilation and debugging of an application.

Note that there are no such macros for release configurations.

Compilation macros

Compilation macros will be checked by the compiler.

Checking the compilation expressions

If you have situations that must be checked before the application is compiled (for example, size of some data types can vary on different platforms), use the ODA_ASSUME() macro, which requires an expression. If this expression becomes false, the compiler will not compile the application. For example:


ODA_ASSUME(sizeof(int) == 8 || sizeof(int) == 4);

This example shows that the application will be compiled only if the size of the integer is 4 or 8 bytes.

Run-time macros

To indicate that an unexpected situation has occurred during application runtime, the Drawings SDK supports a tracking mechanism. You can track any exception or fail during the runtime of a program.

Tracking the fails

To track the simple fails in a program, use the ODA_FAIL() macro, which requires no parameters and displays an "Invalid execution" message with the information about the place of the fail. For example:


try
{
	pDb->writeFile(&fb, fileType, outVer, true);
	odPrintConsoleString(L"\nDatabase has been saved as %ls", pDb->getFilename().c_str());
}
catch (OdError& e)
{
	odPrintConsoleString(L"ODA Error: %ls\n\n", e.description().c_str());
	ODA_FAIL();
}

In that case, when an exception occurrs, you will see a message from ODA_FAIL():


!!! Assertion failed: "Invalid Execution."
	file: d:\work\odTableEx\odtableEx.cpp, line 184

If there is a place in the code that can produce debug messages multiple times (for example, trying to get a database multiple times), you will see the message from the ODA_FAIL() macro many times. But if you want to know only that the problem occurred at least once, use the ODA_FAIL_ONCE() macro, which will show the message of invalid execution only one time. For example:


OdDgDatabase* pDb = getDatabase();
if( !pDb )
{
	ODA_FAIL_ONCE();
	return;
}

So if you have 100 connections to a database, then you will see the message from the macro only one time if problems occur.

Tracking the assertions

The more extended version of ODA_FAIL() is the ODA_ASSERT() macro, which is used when you need to track some specific unexpected situations that can occur during the program run. It contains a boolean expression that is supposed to be true when the assertion executes. If it's false, then the application gives a warning. In Release builds, there are no assertions. This macro prints the reason of the problem and its place in the code. For example:


ODA_ASSERT(val1 == 1 || val2 == 0)

In this example, if the expression is false, the macro will print the next message:


!!! Assertion failed: "val1 == 1 || val2 == 0"
	file: d:\work\odTableEx\odtableEx.cpp, line 195

Just as for the ODA_FAIL() macro, if you have one place in the source code that can produce an "Assertion failed" error multiple times, you should use the ODA_ASSERT_ONCE() macro, which will show the message only one time. For example:


bool isEmpty()
{
	ODA_ASSERT_ONCE(m_pEntityId.get());
	return m_pEntityId->isEmpty(); 
}

Note that ODA_ASSERT and ODA_ASSERT_ONCE print messages when the statement becomes false. That means that you can print the text message using these macros. For example:


ODA_ASSERT(!"My simple message");

By default, assertions in MFC applications display a message box. In console applications they terminate program execution. You can create your own behavior of assertions coming from the Drawings code by substituting a client implementation of the assert function called from the Drawings ODA_ASSERT() macros. Use the odSetAssertFunc() function to set the function that will be used instead of the default one:


odSetAssertFunc(MyAssert);

The diagnostics.h file defines the type of assertion function with the following signature:


typedef void (*OdAssertFunc) (
    const char* expresssion, 
    const char* filename, 
    int nLineNo);

For example:


static void MyAssert(const char* expression, const char* fileName, int nLineNo)
{
  OdString message;
  message.format(L"\n!!! Assertion failed: \"%ls\"\n    file: %ls, line %d\n", OdString(expression).c_str(), OdString(fileName).c_str(), nLineNo);
  odPrintConsoleString(message);
}

Also, there is the ODA_VERIFY() macro, which also helps to track the assertions. The only difference from ODA_ASSERT is that an expression is executed in Release configuration too, but a message is produced in Debug only. For example:


ODA_VERIFY(pFiler->rdBool());

It is the equivalent of the following:


{
  bool bFlag = pFiler->rdBool();
  ODA_ASSERT(bFlag);
}

Tracing

Another way to determine that something just happened is using the ODA_TRACE() macro, which prints user-defined messages. The difference between this macro and the previous is that the ODA_TRACE() macro prints its message into the Debug output during the program run. For example:


ODA_TRACE(L"Something is happening here.\n");

Also there are ODA_TRACE1(), ODA_TRACE2(), and ODA_TRACE3() macros, which allow you to transfer one, two, or three parameters. For example:


ODA_TRACE1("\n Object %s was loaded", pTable->handle().ascii().c_str());
Copyright © 2002 – 2022. Open Design Alliance. All rights reserved.