I have a se of embedded C for a TI processor that need to be unit tested.
For target compilation IAR is used but i am running the tests on a Win7 machine using MinGW GCC.
In the C code there are functions containing state machines that sometimes need to be reset between tests. These state machines often keep their state variable locally static, making that task difficult if not impossible.
I'm not very C++ class savvy but i had an idea about "importing" the C functions into a wrapping C++ class as memberfunctions making it possible to just create a new object whenever a reset i needed. The code below is non functional but it illustrates my idea.
in main.cpp:
#include "statemachine.h"
using namespace std;
class stateMachineWrapper {
public:
extern void stateMachine(void);
};
int main() {
stateMachineWrapper myObject;
myObject.stateMachine();
myObject.stateMachine();
stateMachineWrapper myNewObject;
myNewObject.stateMachine();
myNewObject.stateMachine();
return 0;
}
in statemachine.h:
void stateMachine(void);
in statemachine.c:
#include <stdio.h>
void stateMachine(void)
{
static int myState = 0;
switch(myState)
{
case 0:
{
printf("Init State");
myState = 1;
break;
}
case 1:
{
printf("Second state");
break;
}
default:
{
printf("Default");
break;
}
}
}
Alterations to the statemachine.c/.h is not encouraged since it can be considered "legacy".
Any other solutions is of course welcome as well!
The wrapping won't help. The C++ code has no way of reaching the internal static variable inside the state machine written in C.
One solution is to use dynamic code loading for the C parts, that will make the early initialization code and clear the static variable.
You could also split the tests into multiple executables, that has the same effect but probably larger overhead (=tests will run more slowly).
#unwind sent me looking at dynamic code loading!
Reading these:
Dynamically load a function from a DLL and http://www.transmissionzero.co.uk/computing/building-dlls-with-mingw/ gave me enough to concoct the following solution.
in statemachine.h:
void stateMachine(void);
in statemachine.c:
#include <stdio.h>
void stateMachine(void)
{
static int myState = 0;
switch(myState)
{
case 0:
{
printf("Init State");
myState = 1;
break;
}
case 1:
{
printf("Second state");
break;
}
default:
{
printf("Default");
break;
}
}
}
in statemachinelib.c:
#include "statemachine.h"
__declspec(dllexport) void __cdecl statemachineWrap()
{
stateMachine();
}
in main.c:
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
typedef int (__stdcall *f_funci)();
int main(int argc, char **argv)
{
HINSTANCE hGetProcIDDLL = LoadLibrary("statemachinelib.dll");
f_funci funci = (f_funci)GetProcAddress(hGetProcIDDLL, "statemachineWrap");
funci();
funci();
funci();
FreeLibrary(hGetProcIDDLL); //Windows detects that no one is using this library anymore and unloads it from memory, giving the new LoadLibrary a fresh instance
hGetProcIDDLL = LoadLibrary("statemachinelib.dll");
funci = (f_funci)GetProcAddress(hGetProcIDDLL, "statemachineWrap");
funci();
funci();
funci();
return 0;
}
In this code i have omitted a lot of safety statements such as checking if the DLL could be loaded, if the function is found, whether we want too dllexport or dllimport and so on only to make it easier to grasp what is going on. If you are going to implement this in any real project you should at least read both of the resources i mentioned above.
compilation of the DLL using MinGW:
>gcc -c statemachine.c statemachinelib.c
>gcc -o statemachinelib.dll -s -shared statemachinelib.o statemachine.o -Wl,--subsystem,windows
compilation of the executable, also MinGW:
>gcc -o main.exe main.c
execution yields:
>main.exe
Init State
Second state
Second state
Init State
Second state
Second state
I'll just leave this here for a few days and if no one objects i will mark this as my accepted answer!
Edit: I have elaborated a bit and there's another (solved) question from me here with just a slight tweak Exporting a function, cast into a pointer through a DLL
Related
I have been trying to figure out why this is happening and maybe it is just due to inexperience at this point but could really use some help.
When I run my code, which is compiled into a DLL using C++20, I get that a debug assertion has failed with the expression being __acrt_first_block == header.
I narrowed down where the code is failing, but the weird part is that it runs just fine when I change the Init(std::string filePath function signature to not contain the parameter. The code is below and hope someone can help.
Logger.h
#pragma once
#include "../Core.h"
#include <memory>
#include <string>
#include "spdlog/spdlog.h"
namespace Ruby
{
class RUBY_API Logger
{
public:
static void Init(std::string filePath);
inline static std::shared_ptr<spdlog::logger>& GetCoreLogger() { return coreLogger; }
inline static std::shared_ptr<spdlog::logger>& GetClientLogger() { return clientLogger; }
private:
static std::shared_ptr<spdlog::logger> coreLogger;
static std::shared_ptr<spdlog::logger> clientLogger;
};
}
Logger.cpp
namespace Ruby
{
std::shared_ptr<spdlog::logger> Logger::coreLogger;
std::shared_ptr<spdlog::logger> Logger::clientLogger;
void Logger::Init(std::string filePath)
{
std::string pattern{ "%^[%r][%n][%l]: %v%$" };
auto fileSink = std::make_shared<spdlog::sinks::basic_file_sink_mt>(filePath, true);
// Setup the console and file sinks
std::vector<spdlog::sink_ptr> coreSinks;
coreSinks.push_back(std::make_shared<spdlog::sinks::stdout_color_sink_mt>());
coreSinks.push_back(fileSink);
// Bind the sinks to the core logger.
coreLogger = std::make_shared<spdlog::logger>("RUBY", begin(coreSinks), end(coreSinks));
// Set the Patterns for the sinks
coreLogger->sinks()[0]->set_pattern(pattern);
coreLogger->sinks()[1]->set_pattern(pattern);
// Tell spdlog to flush the file loggers on trace or worse message (can be changed if necessary).
coreLogger->flush_on(spdlog::level::trace);
// Set the default level of the logger
coreLogger->set_level(spdlog::level::trace);
// Do the same for the client logger
std::vector<spdlog::sink_ptr> clientSinks;
clientSinks.push_back(std::make_shared<spdlog::sinks::stdout_color_sink_mt>());
clientSinks.push_back(fileSink);
clientLogger = std::make_shared<spdlog::logger>("APP", begin(clientSinks), end(clientSinks));
clientLogger->sinks()[0]->set_pattern(pattern);
clientLogger->sinks()[1]->set_pattern(pattern);
clientLogger->flush_on(spdlog::level::trace);
clientLogger->set_level(spdlog::level::trace);
}
}
Entrypoint.h
#pragma once
#ifdef RB_PLATFORM_WINDOWS
extern Ruby::Application* Ruby::CreateApplication();
int main(int argc, char** argv)
{
Ruby::Logger::Init("../Logs/Recent_Run.txt");
RB_CORE_INFO("Initialized the logger.");
auto app = Ruby::CreateApplication();
app->Run();
delete app;
return 0;
}
#else
#error Ruby only supports windows
#endif // RB_PLATFORM_WINDOWS
For anyone else who runs into a similar problem, here is how I fixed it.
Essentially the function signature for the Init() function was the problem. The std::string parameter was causing the debug assertion to fire, my best guess as of right now was because of move semantics but that part I am still not sure on. So there are a couple of ways that I found to fix this.
Method 1:
Make the parameter a const char*. I don't quite like this approach as it then relies on C style strings and if you are trying to write a program in modern C++, this is a huge step backwards.
Method 2:
Make the parameter a const std::string&. Making it a const reference to a string prevents the move semantics (again as far as I know) and the assertion no longer fires. I prefer this fix as it keeps the program in modern C++.
I hope this helps anyone who has similar issues, and be careful with statics and move semantics.
I have two functions in C library that I am making.
One is a setup function, other is a function that does some operations. I want the second operations function to print an error if the setup function has not run before it.
What would be the best way to do this?
Here is what I have in my mind, but I am not sure if that is how it is done.
The setup function:
void setup_function()
{
#ifndef FUNCTION_SETUP
#define FUNCTION_SETUP
a_init();
b_init();
c_init();
#endif
}
And the operations function:
bool operations()
{
#ifdef FUNCTION_SETUP
try
{
/* My code */
return true;
}
catch (...)
{
Serial.println("Error in operations");
return false;
}
#elif Serial.println("Function not setup. Please use setup_function() in void setup()");
#endif
}
#ifndef only checks whether this function was defined somewhere for the compiler and won't affect runtime.
best way to do this is through use of a global variable that changes value once the setup function is executed. if you're defining these functions in classes you could use static data member and setup function
C has a pre-processing command #error that can be used to trigger a stop to the compiling. However, the compilation unit is processed in order, not ran. Some programmes need to just run to see, (which is related to the halting problem.)
The idiomatic way to to runtime checks is with assert, as in this C99 example. (You would #include <cassert> in C++.)
#include <stdbool.h>
#include <assert.h>
static bool is_setup; // Can be optimized away with -D NDEBUG.
static void setup_function(void) {
assert(!is_setup && (is_setup = true));
}
static bool operations(void) {
assert(is_setup);
return true;
}
int main(void) {
//setup_function(); // Triggers `assert` if omitted.
operations();
return 0;
}
However, C++ has techniques that encourage RAII; when possible, one should generally use this to set up an object on acquisition and manage the object throughout it's lifetime.
I'm writing a program (macOS, clang++ compiler, only AppleSilicon at the moment) that I can extend later by providing custom plugins (dynamic library, loaded at runtime) which use main program's public interface.
test.hpp - public interface:
#if defined(MAGIC_PLUGIN)
# define MAGIC_EXPORT /* nothing */
#else
# define MAGIC_EXPORT __attribute__((visibility("default")))
#endif
MAGIC_EXPORT
void testCall();
test.cpp - main programm:
#include <stdio.h>
#include <dlfcn.h>
#include "test.hpp"
// Declare a function to call from a loaded plugin
typedef void (* plugin_call_func)(void);
int main(int argc, char** argv) {
// Load library
const char* libraryName = "plugin.dylib";
void* library = dlopen(libraryName, RTLD_NOW);
if (library == nullptr) {
printf("Cannot open library\n");
return 1;
}
// Get function from loaded library
plugin_call_func pluginCall = reinterpret_cast<plugin_call_func>(
dlsym(library, "pluginCall"));
if (pluginCall == nullptr) {
printf("Cannot find the pluginCall function\n");
return 2;
}
// Execute loaded function
pluginCall();
// Forget function and close library
pluginCall = nullptr;
auto libraryCloseResult = dlclose(library);
if (libraryCloseResult != 0) {
printf("Cannot close library\n");
return 3;
}
return 0;
}
// Public function, should be called from a plugin
void testCall() {
printf("Test call\n");
}
plugin.cpp - plugin's source:
#define MAGIC_PLUGIN
#include <stdio.h>
#include "test.hpp"
__attribute__((visibility("default")))
extern "C" void pluginCall(void) {
printf("Plugin call\n");
testCall();
}
First, I compile main app:
clang++ -std=c++20 -fvisibility=hidden -target arm64-apple-macos12 test.cpp -o test
The nm --defined-only test shows these symbols:
0000000100003ee4 T __Z8testCallv
0000000100000000 T __mh_execute_header
0000000100003dcc t _main
Mangled __Z8testCallv is what I need. Everything looks good so far. But then I try to compile the plugin as dynamic library...
clang++ -std=c++20 -fvisibility=hidden -dynamiclib -g -current_version 0.1 -target arm64-apple-macos12 plugin.cpp -o plugin.dylib
and get this error:
Undefined symbols for architecture arm64:
"testCall()", referenced from:
_pluginCall in plugin-38422c.o
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Well, it's kind of fair, I can understand this, because the dynamic library does not know that testCall is somewhere implemented. So I want to say it that it does not have to worry about testCall's existence.
I tried to research how to do this, looked up man pages, read tons of stack overflow answers, and what I only found that works is adding these flags to linker:
-Wl,-undefined,dynamic_lookup
It works, the library compiles and the app works as expected. But I don't really want to use dynamic_lookup because it will mark every undefined symbol in the library as resolved, which may lead to some bad consequences. I want to tell the linker only about existence of the main program's public symbols.
What am I missing? Is there any better solution than dynamic_lookup?
Your best bet is to manually do the work that's done by the library loader. That is: populating function pointers. After all, the plugin->main binding is already done manually, so doing the same thing the other way around makes sense.
You can make this process essentially transparent by carefully crafting the header shared by the plugin and main application. The only tricky part is handling ODR for plugins that are composed of multiple source files.
Since this is a C++ question, here's what it could look like with a RAII wrapper. The ODR conundrum is handled via the PLUGIN_MAIN macro that should only be defined in one of a plugin's sources.
test_plugin.hpp
using pluginCall_fn = void(*)();
using testCall_fn = void(*)();
#if !defined(MAIN_APPLICATION)
#if defined(PLUGIN_MAIN)
#define EXPORTED_FROM_MAIN __attribute__((visibility("default")))
#else
#define EXPORTED_FROM_MAIN __attribute__((visibility("default"))) extern
#endif
extern "C" {
// Declare symbols provided by the plugin
__attribute__((visibility("default"))) void pluginCall();
// etc...
// Declare/define pointers that will be populated by the main application
EXPORTED_FROM_MAIN testCall_fn testCall;
// etc...
}
#undef EXPORTED_FROM_MAIN
#else // In the main app.
#include <stdexcept>
// Declare "symbols" provided by the main application
void testCall();
// Utility class to load/unload a dynamic library.
// Probably belongs in its own header...
struct loaded_library final {
loaded_library(const char* libName)
: handle_(dlopen(libName, RTLD_NOW)) {
if(!handle_) {
throw std::runtime_error("failed to load plugin");
}
}
loaded_library(const loaded_library&) = delete;
loaded_library& operator=(const loaded_library&) = delete;
loaded_library(loaded_library&& rhs) : handle_(rhs.handle_) {
rhs.handle_ = nullptr;
}
loaded_library& operator=(loaded_library&& rhs) {
handle_ = rhs.handle_;
rhs.handle_ = nullptr;
return *this;
}
~loaded_library() {
if(handle_) {
dlclose(handle_);
}
}
template<typename T>
T get_symbol(const char* symbol) {
T result = reinterpret_cast<T>(dlsym(handle_, symbol));
if(!result) {
throw std::runtime_error("missing symbol");
}
return result;
}
private:
void* handle_;
};
// Plugin interface.
struct loaded_plugin final {
loaded_plugin(const char* libName)
: lib_(libName) {
// Load functions from plugin
pluginCall = lib_.get_symbol<pluginCall_fn>("pluginCall");
// ...
// Assign callbacks to plugin
*lib_.get_symbol<testCall_fn*>("testCall") = &testCall;
// ...
// Call the plugin's init function here if applicable.
}
pluginCall_fn pluginCall;
private:
loaded_library lib_;
};
#endif
plugin.cpp
#define PLUGIN_MAIN
#include "test_plugin.hpp"
#include <stdio.h>
void pluginCall() {
printf("Plugin call\n");
testCall();
}
test.cpp
#define MAIN_APPLICATION
#include "test_plugin.hpp"
int main(int argc, char** argv) {
const char* libraryName = "plugin.dylib";
loaded_plugin plugin(libraryName);
plugin.pluginCall();
}
// Public function, should be called from a plugin
void testCall() {
printf("Test call\n");
}
You may find that this code is a bit on the fragile side of things, since a few different portions of test_plugin.hpp need to be kept in sync.
This can be worked around with the use of X-Macros, at the cost of confusing IDEs and hurting code legibility. I wouldn't go down that road until the APIs in question become unwieldingly large.
I am using VS2019
Trying to call a thread in DLL. to run two executables simultaneously with detach
following threads worked when I Run a normal c++ program
I get error
Error C3867 'myClass::runexeone': non-standard syntax; use '&' to create a pointer to member myGateway C:\Users\user\Downloads\Demo\myGateway\myplugin.cpp 21
plugin header
#include <windows.h>
#include <iostream>
#include <thread>
#define MYPLUGIN_EXPORT __declspec(dllexport)
extern "C"
{
MYPLUGIN_EXPORT void WINAPI OnStart();
}
pluging.cpp
#include "plugin.h"
using namespace std;
class myClass
{
public:
myClass()
{
}
~myClass()
{
}
void onStart()
{
std::thread(runexeone).detach();
std::thread(runexetwo).detach();
}
void runexeone()
{
int exerunpne = system("cmd /C \"%MY_ROOT%\\bin\\Mytest.exe\" -ORBEndpoint iiop://localhost:12345 -d");
}
void runexetwo()
{
int exeruntwo = system("cmd /C \"%MY_ROOT%\\bin\\Mytest_2.exe\" -ORBEndpoint iiop://localhost:12345 -d");
}
};
myClass& getmyclass()
{
static myClass myclass;
return myclass;
}
MYPLUGIN_EXPORT void WINAPI OnStart()
{
getmyClass().onStart();
}
The problem is that runexeone is an unqualified name of a member function, and std::thread needs something executable. runexeone isn't. VC++ tries to guess from context what you mean, but the suggestion isn't enough. Even if you had written &myClass::runexeone, it still wouldn't have worked, because myClass::runexeone also needs a this pointer. You can fix the latter problem by making it static.
Compiler suggestions work best when there's just one problem.
As MSalters already mentioned, you provided the wrong data type for the functor for std::thread. If you cannot make the method static (which you can actually at least for the current state of your code, but to let this not be unstated here), you can do this
void onStart()
{
std::thread(std::bind(&myClass::runexeone, this)).detach();
}
But be careful about the lifetime/existence of your object/this!
i am trying to make a c++ DLL project in VS2017 to use in a VB.NET VS2017 project.
the c++ code;
MyCudaLib.h
#ifndef DLL3_H
#define DLL3_H
#ifdef DLL3_EXPORTS
#define DLL3_API __declspec(dllexport)
#else
#pragma message("automatic link to MyCudaLib.LIB")
//#pragma comment(lib, "MyCudaLib.lib")
#define DLL3_API __declspec(dllimport)
#endif
int* __stdcall test_array();
#endif //DLL3_H
MyCudaLib.cpp
#include <stdio.h>
#include "MyCudaLib.h"
#include <Windows.h>
#include <stdexcept>
#include <sstream>
using namespace std;
#define DLL3_EXPORTS
BOOL APIENTRY DllMain(HANDLE /*hModule*/,
DWORD ul_reason_for_call,
LPVOID /*lpReserved*/
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
int* __stdcall test_array()
{
int arr[]{ 30,50,60,70 };
return arr;
}
in VB part of the code
Private Declare Function test_array Lib "MyCudaLib.dll" () As Integer()
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Console.WriteLine(test_array(0))
End Sub
is my exporting part of code is wrong? c++ part compiled wtihout error but VB part of the code wont work gives error.
System.Runtime.InteropServices.MarshalDirectiveException: ''return value' cannot arranged.
Note: My point to make a proper working function in c++ is to write a CUDA code to program the GPU. I can write and compile code in CUDA in c++ without problem. But students in my class cannot program in c++ and i can't write more complex code with c++. So, i thought, if i can use the cuda function outside the c++ environment, we all can code it with vb or other languages.
Sure your function compiles fine - it is defined as a function returning a single int and does so as well (return *arr; is equivalent to return arr[0];).
From MarshalDirectiveException
The exception that is thrown by the marshaler when it encounters a MarshalAsAttribute it does not support.
As you did not provide an English error message, I can only guess what's happening now, but there are only few options available:
You have yet another error with your marshaling not visible here.
The function is not recognised due to C++ name mangling (see below).
Incompatibility between int returned in function and expected array is recognised.
The int is interpreted as pointer – but pointer size does not match and the type cannot be marshaled at all.
If you want to return an array, you need to define your function as such:
int* getArray()
// ^
{
static int a[] = {1, 2, 3};
// ^^^^^^ we cannot return an array with local storage duration, so make it
// static, global, or allocate one on heap (new int[]; but assure the
// array to be delete[]d appropriately again to avoid memory leak)
return a; // NOT dereferenced!
}
Be aware that you have C++ name mangling applied. You might possibly prefer a C-kompatible interface:
extern "C" int* getArray();
However, you cannot return C++ data types this way like std::vector – which in most cases even is preferrable, though, as those types usually are incompatible across different implementations (DLL compiled with MSVS, EXE with GCC/MinGW) anyway.
Finally be aware that via a pointer, you lose information about array size! You need to find other means to provide this information to the user of your library.