Support Board
Date/Time: Thu, 28 Nov 2024 00:49:59 +0000
[Programming Help] - LoadLibrary works in test wrapper but not in SC study?
View Count: 264
[2023-06-16 01:01:33] |
User133994 - Posts: 80 |
Support, Should any special considerations be given for using LoadLibrary/GetProcAddress in a study function? this test wrapper works fine: #include <windows.h>
#include <iostream> typedef float(*HelloWorldFunction)(float); int main() { // Load the DLL HMODULE hDLL = LoadLibraryExW(L"C:\\SierraChart\\vlk\\DLLvlkfunctions.dll", NULL, LOAD_WITH_ALTERED_SEARCH_PATH); if (hDLL == NULL) { std::cout << "Failed to load DLL. Error code: " << GetLastError() << std::endl; return 1; } // Get the hello_world function address HelloWorldFunction helloWorld = reinterpret_cast<HelloWorldFunction>(GetProcAddress(hDLL, "hello_world")); if (helloWorld == NULL) { std::cout << "Failed to get function address. Error code: " << GetLastError() << std::endl; FreeLibrary(hDLL); return 1; } // Call the hello_world function float result = helloWorld(5.0f); std::cout << "Result: " << result << std::endl; // Free the DLL module FreeLibrary(hDLL); return 0; } this study snippet throws exceptions: typedef float(*HelloWorldFunction)(float); ... struct pDllWrapper ... HMODULE hDLL = LoadLibraryExW(L"C:\\SierraChart\\vlk\\DLLvlkfunctions.dll", NULL, LOAD_WITH_ALTERED_SEARCH_PATH); if (hDLL == NULL) { SCString LogMessage; LogMessage.Format("pDW Failed to load DLL. Error code: %lu", GetLastError()); sendDebugOnce(sc, LogMessage, r_lastDebugString_); throw std::runtime_error("pDW Failed to load DLL"); } // Get the hello_world function address helloWorld = reinterpret_cast<HelloWorldFunction>(GetProcAddress(hDLL, "hello_world")); if (helloWorld == NULL) { SCString LogMessage; LogMessage.Format("pDW Failed to get function address. Error code: %lu", GetLastError()); sendDebugOnce(sc, LogMessage, r_lastDebugString_); FreeLibrary(hDLL); throw std::runtime_error("pDW Failed to get function address"); } float callHelloWorld(float num) { // Call the hello_world function return helloWorld(num); } bool runHelloWorld(SCStudyInterfaceRef& sc, SCInputRef& Input_showmessag, float num, float& result) { try { result = callHelloWorld(num); if (Input_showmessag.GetYesNo()) { // Check if debug messages should be shown SCString LogMessage; LogMessage.Format("pDW Result: %f", result); sendDebugOnce(sc, LogMessage, r_lastDebugString_); } return true; // Indicate success } catch (std::runtime_error& e) { SCString LogMessage; LogMessage.Format("pDW Exception: %s", e.what()); sendDebugOnce(sc, LogMessage, r_lastDebugString_); return false; // Indicate failure } } ... inside scsf_dllCallTest... if (sc.Index == 0) { // pointer initialization pDW = reinterpret_cast<pDllWrapper*>(sc.GetPersistentPointer(pDllWrapper_pkey)); // assign persistent pointer to pDllWrapper struct if (pDW == nullptr) sc.SetPersistentPointer(pDllWrapper_pkey, new pDllWrapper(sc, r_lastDebugString)); } // Use the pDW float result; if (!pDW->runHelloWorld(sc, Input_show_debug, 5.0f, result)) { // Handle error case SCString LogMessage; LogMessage.Format("!!!ERROR =%d.", sc.Index); sendDebugOnce(sc, LogMessage, r_lastDebugString); } else { // Use result if (Input_show_debug.GetYesNo() ){ SCString LogMessage; LogMessage.Format("Sending message 1x =%d. pdw input: %f, result:%f ", sc.Index, 5.0f, result); sendDebugOnce(sc, LogMessage, r_lastDebugString); } } Yes, I do use sc.LastCallToFunction to delete pDW. I have tried initializing pDW outside the sc.Index = 0 block, but that doesn't seem to help. The hello world function simply multiplies the input x2: thus you see in the output 5.00 and 10.00. The message log shows a CPU exception, but then proceeds to call the DLL function and has the proper outputs(?): Warning: The Custom DLL study "_install.scsf_dllCallTest" has just caused a CPU exception. | 2023-06-15 20:48:28.488 *
Warning: This Custom DLL study may cause Sierra Chart to be unstable until you remove the study from the chart and restart Sierra Chart. | 2023-06-15 20:48:28.488 * Chart: NQU23_FUT_CME[M] 5 Min #1 | Study: _install v0.07 | pDW Result: 10.000000 | 2023-06-15 20:48:28.679 Chart: NQU23_FUT_CME[M] 5 Min #1 | Study: _install v0.07 | Sending message 1x =0. pdw input: 5.000000, result:10.000000 | 2023-06-15 20:48:28.679 Chart: NQU23_FUT_CME[M] 5 Min #1 | Study: _install v0.07 | pDW Result: 10.000000 | 2023-06-15 20:48:28.679 Chart: NQU23_FUT_CME[M] 5 Min #1 | Study: _install v0.07 | Sending message 1x =1. pdw input: 5.000000, result:10.000000 | 2023-06-15 20:48:28.679 Chart: NQU23_FUT_CME[M] 5 Min #1 | Study: _install v0.07 | pDW Result: 10.000000 | 2023-06-15 20:48:28.679 Chart: NQU23_FUT_CME[M] 5 Min #1 | Study: _install v0.07 | Sending message 1x =2. pdw input: 5.000000, result:10.000000 | 2023-06-15 20:48:28.679 Chart: NQU23_FUT_CME[M] 5 Min #1 | Study: _install v0.07 | pDW Result: 10.000000 | 2023-06-15 20:48:28.679 Chart: NQU23_FUT_CME[M] 5 Min #1 | Study: _install v0.07 | Sending message 1x =3. pdw input: 5.000000, result:10.000000 | 2023-06-15 20:48:28.679 Chart: NQU23_FUT_CME[M] 5 Min #1 | Study: _install v0.07 | pDW Result: 10.000000 | 2023-06-15 20:48:28.679 Any ideas why the CPU exception is thrown for this simple example? It does appear at the beginning..maybe before something is loaded? Also, if you have a working DLL call study that uses LoadLibrary/GetProcAddress in a study with an external DLL file that doesn't have CPU exceptions in the log, please provide a copy to me so I can begin with a working example. Maybe there is an obvious answer that I am missing. Please help. Your assistance is much appreciated. |
To post a message in this thread, you need to log in with your Sierra Chart account: