Peter from S.C.C.C.

Verified Members
  • Content count

    754
  • Joined

  • Last visited

  • Days Won

    3

Peter from S.C.C.C. last won the day on March 21

Peter from S.C.C.C. had the most liked content!

Community Reputation

139 Excellent

1 Follower

About Peter from S.C.C.C.

  • Rank
    Advanced Member

Profile Information

  • Gender
    Male

Uncategorized

  • Location
    Canada

Recent Profile Visitors

1,114 profile views
  1. This applies also to DLL's which are called by the ft referenced dll's. Would an external application called by Mastercam be able to call the functions then release the dll's. I believe there is a RunUserApplication function in the chook sdk.
  2. was changed to : auto splitlines = StringManipulation::split(line, _T("|")); Since using a whitespace as a delimeter is a bad choice when loading paths that could have folder names or files with whitespaces in them..
  3. In this case it were to return 0 the functions would be pushed to the front of the queue, I could check the vector of DllFunction structs and if the struct Priority parameter has a value less than one, send an error message to the event logger and abort the process. The priority value tells Mastercam what order the functions need to be run in. The other options would be your suggestion, or wrapping the .net function that returns nullptr on failure. I have not actually used exceptions before in my code..
  4. Nethook LoadDll : https://github.com/PeterRussellEvans/LoadDll Function DllExport : https://github.com/PeterRussellEvans/MastercamDllExport
  5. From what I can see Mastercam won't release the dll even if I call AfxFreeLibrary. The actual process lets Mastercam successfully call as many dll's are stacked in the process, but it will not allow us to call free library.
  6. Check out the entity unions : for example entity.u.ar is the arc union, that is where you will find information.
  7. Hi Karsten, I am not sure exactly what you are trying to do, however here is a snippet of chains being created from already selected arcs , then the chains being reversed and added into an operation : std::vector<CHAIN*>VectorOfChains; //get everything auto onlyVisible = false; auto succf = false, suc = false; //our current entity ent entity; DB_LIST_ENT_PTR foundPtr; // the first entity in the database auto eptr = db_start; //loop through the database do { //get the next entity in the database get_raw_ent(onlyVisible, &eptr, &foundPtr, &entity, 0, A_ID, &succf); if (succf) { //if the entity is an arc if (entity.id == A_ID) { //if the entity is ALIVE if (sel_bit_is_on(&entity, ALIVE_BIT)) { //if the entity is NOT BLANK if (sel_bit_is_off(&entity, BLANK_BIT)) { //if the entity is SELECTED if (sel_bit_is_on(&entity, SELECT_BIT)) { //unselect the entity sel_bit_turn_off(&entity, SELECT_BIT); //write to the entity that it is unselected write_ent_sel(&entity, entity.eptr); //update the graphics repaint_graphics(); CHAIN *chain; short err = alloc_chain(&chain, FALSE /* partial*/); bool result = (err == 0 && chain != nullptr); if (result) { CHAIN_ENT *last_chain_ent = nullptr; short errCode = add_curve_to_chain(&entity, 0, TRUE, 0, chain, &last_chain_ent); if (errCode != CHAIN_OK) // bail out ! { result = false; } } if (result) { VectorOfChains.push_back(chain); } //if (ChainDIRECTION(chain, 1) == flip) //{ // reverse_chain(chain); //} } } } } } } while (succf); //create a blank pocket operation operation op; op.opcode = TP_POCKET; DB_LIST_ENT_PTR ptr; bool bsuccf; operation_manager(&op, OPMGR_INIT_ADD, &ptr, &bsuccf); auto index = 1; CString chaininfo; for(auto chain : VectorOfChains) { switch (ChainDIRECTION(chain, 1)) { case 0: chaininfo.Format(_T("Chain #%d is clockwise"), index); MessageBox(nullptr, chaininfo,_T("MESSAGE"),MB_OK); break; case 1: chaininfo.Format(_T("Chain #%d is counterclockwise"), index); MessageBox(nullptr, chaininfo, _T("MESSAGE"), MB_OK); break; } reverse_chain(chain); switch (ChainDIRECTION(chain, 1)) { case 0: chaininfo.Format(_T("Chain #%d is clockwise"), index); MessageBox(nullptr, chaininfo, _T("MESSAGE"), MB_OK); break; case 1: chaininfo.Format(_T("Chain #%d is counterclockwise"), index); MessageBox(nullptr, chaininfo, _T("MESSAGE"), MB_OK); break; } //copy chains to operation chain_manager_info cmi; cmi.mode = CHNMGR_ADD; cmi.chns = chain; cmi.op_idn = op.op_idn; chain_manager(&cmi, TP_CHN_ALL, &succf); free_chain(&chain); index++; } HTH
  8. Yeah, that is much better, even if that did not exist, I could have defined my own, that is a very good one.
  9. The load library function is a bit long because it is setup to load more than 1 function at a time. Overall I am loading the information and functions at runtime. I want Mastercam to Release the dll's containing the c++ code when the chook ends so I won"t have to reload mastercam, I also want to try reusing code without recompiling it. ^Thanks for the tips. Maybe I can add a macro to use AfxLoadLibrary and AfxFreeLibrary if there is a mastercam version.. Cool, thanks for the information, I was not aware of that option..
  10. Peter from S.C.C.C.

    Changing drill speed mid cycle

    Maybe it is a lot, but the cutting speed for that material is very high.. I would try it. Maybe close the door lol. If you have a welder, you could weld one onto some drill rod, I have seen it before, it worked I suppose.
  11. Hi, here is how to load functions from dll using a text file to tell your application the name of the function and .dll file to use at runtime : Application : Main.Cpp #include <windows.h> #include <atlstr.h> #include <iostream> #include <fstream> #include <string> #include <vector> #include <algorithm> #include <filesystem> #include <conio.h> #include <string> #include <iostream> #include <clocale> #include <locale> #include <vector> #pragma once #ifdef UNICODE //Test to see if we're using wchar_ts or not. typedef std::wstring StringType; #else typedef std::string StringType; #endif // /////////////////////////// /////////////////////////// // //start of struct definitions// // /////////////////////////// /////////////////////////// // //the parameter struct that is both input and output from our function extern "C" struct DllFunctionParams { std::vector<bool>vectorofbools; std::vector<int>vectorofints; std::vector<double>vectorofdoubles; std::vector<HWND>vectorofhwnds; std::vector<CString>vectorofcstrings; }; //our function definition extern "C" { typedef DllFunctionParams(*f_funci)(DllFunctionParams&); } //the parameter struct that holds the data about our current dll function extern "C" struct DllFunction { StringType DllName; StringType DllFunctionName; int Priority; f_funci function; }; // /////////////////////////// /////////////////////////// // //start of struct definitions// // /////////////////////////// /////////////////////////// // // /////////////////////////// /////////////////////////// // //start of string functions namespace// // /////////////////////////// /////////////////////////// // namespace StringManipulation { StringType pathAppend(const StringType & p1, const StringType & p2); std::string wstrtostr(const std::wstring & wstr); double StringToDouble(StringType input); int StringToInt(StringType input); StringType GetExtension(StringType filename); StringType GetBaseFilename(StringType filename); StringType GetCurrentPath(); std::vector<StringType> GetListOfFiles(StringType path); bool PathExists(const StringType & s); inline bool FileExists(const StringType & name); std::vector<StringType> GetLinesFromFile(StringType filename); std::vector<StringType> split(StringType stringToBeSplitted, StringType delimeter); } // /////////////////////////// /////////////////////////// // //end of string functions namespace// // /////////////////////////// /////////////////////////// // // /////////////////////////// /////////////////////////// // //start of string functions// // /////////////////////////// /////////////////////////// // StringType StringManipulation::pathAppend(const StringType& p1, const StringType& p2) { char sep = '/'; StringType tmp = p1; #ifdef _WIN32 sep = '\\'; #endif if (p1[p1.length()] != sep) { // Need to add a tmp += sep; // path separator return(tmp + p2); } else return(p1 + p2); } std::string StringManipulation::wstrtostr(const std::wstring &wstr) { std::string strTo; char *szTo = new char[wstr.length() + 1]; szTo[wstr.size()] = '\0'; WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, szTo, (int)wstr.length(), NULL, NULL); strTo = szTo; delete[] szTo; return strTo; } double StringManipulation::StringToDouble(StringType input) { CString c_str = input.c_str(); // Convert a TCHAR string to a LPCSTR CT2CA pszConvertedAnsiString(c_str); // construct a std::string using the LPCSTR input std::string strStd(pszConvertedAnsiString); return atof(strStd.c_str()); /*c_str is needed to convert string to const char*/ } int StringManipulation::StringToInt(StringType input) { CString c_str = input.c_str(); // Convert a TCHAR string to a LPCSTR CT2CA pszConvertedAnsiString(c_str); // construct a std::string using the LPCSTR input std::string strStd(pszConvertedAnsiString); return atoi(strStd.c_str()); /*c_str is needed to convert string to const char*/ } StringType StringManipulation::GetExtension(StringType filename) { //store the position of last '.' in the file name int position = filename.find_last_of(_T(".")); //store the characters after the '.' from the file_name string StringType result = filename.substr(position + 1); //print the result return result; } StringType StringManipulation::GetBaseFilename(StringType filename) { size_t pos = filename.rfind(_T(".")); if (pos == StringType::npos) //No extension. return filename; if (pos == 0) //. is at the front. Not an extension. return filename; return filename.substr(0, pos); } StringType StringManipulation::GetCurrentPath() { #ifdef UNICODE //Test to see if we're using wchar_ts or not. wchar_t buffer[MAX_PATH]; #else char buffer[MAX_PATH]; #endif GetModuleFileName(NULL, buffer, MAX_PATH); StringType::size_type pos = StringType(buffer).find_last_of(_T("\\/")); return StringType(buffer).substr(0, pos); } std::vector<StringType> StringManipulation::GetListOfFiles(StringType path) { std::vector<StringType>stringvector; WIN32_FIND_DATA fileData; memset(&fileData, 0, sizeof(WIN32_FIND_DATA)); CString string; string.Format(_T("%s\\*"), path.c_str()); HANDLE handle = FindFirstFile(string, &fileData); if (handle != INVALID_HANDLE_VALUE) { do { if (_tcscmp(fileData.cFileName, _T(".")) != 0 && // ignore "." and ".." _tcscmp(fileData.cFileName, _T("..")) != 0) { stringvector.push_back(fileData.cFileName); } } while (FindNextFile(handle, &fileData)); FindClose(handle); } return stringvector; } bool StringManipulation::PathExists(const StringType &s) { struct stat buffer; CString c_str = s.c_str(); // Convert a TCHAR string to a LPCSTR CT2CA pszConvertedAnsiString(c_str); // construct a std::string using the LPCSTR input std::string strStd(pszConvertedAnsiString); return (stat(strStd.c_str(), &buffer) == 0); } inline bool StringManipulation::FileExists(const StringType& name) { CString c_str = name.c_str(); // Convert a TCHAR string to a LPCSTR CT2CA pszConvertedAnsiString(c_str); // construct a std::string using the LPCSTR input std::string strStd(pszConvertedAnsiString); struct stat buffer; return (stat(strStd.c_str(), &buffer) == 0); } std::vector<StringType> StringManipulation::GetLinesFromFile(StringType filename) { auto count = 0; std::vector<StringType> stringvector; if (FileExists(filename)) { std::ifstream file(filename); std::string str; while (std::getline(file, str)) { CString c_str = str.c_str(); StringType stringtype(c_str); stringvector.push_back(stringtype); count++; // Process str } } return count > 0 ? stringvector : std::vector<StringType>(0); } std::vector<StringType> StringManipulation::split(StringType stringToBeSplitted, StringType delimeter) { std::vector<StringType> splittedString; int startIndex = 0; int endIndex = 0; while ((endIndex = stringToBeSplitted.find(delimeter, startIndex)) < stringToBeSplitted.size()) { StringType val = stringToBeSplitted.substr(startIndex, endIndex - startIndex); splittedString.push_back(val); startIndex = endIndex + delimeter.size(); } if (startIndex < stringToBeSplitted.size()) { StringType val = stringToBeSplitted.substr(startIndex); splittedString.push_back(val); } return splittedString; } // /////////////////////////// /////////////////////////// // //end of string functions// // /////////////////////////// /////////////////////////// // // /////////////////////////// /////////////////////////// // //start of GetProcAddress header// // /////////////////////////// /////////////////////////// // bool GetProcAddresses(HINSTANCE * hLibrary, #ifdef UNICODE //Test to see if we're using wchar_ts or not. LPCWSTR lpszLibrary, INT nCount, ...); #else LPCSTR lpszLibrary, INT nCount, ...); #endif // /////////////////////////// /////////////////////////// // //end of GetProcAddress header// // /////////////////////////// /////////////////////////// // // /////////////////////////// /////////////////////////// // //start of GetProcAddress function// // /////////////////////////// /////////////////////////// // //GetProcAddresses //Argument1: hLibrary - Handle for the Library Loaded //Argument2: lpszLibrary - Library to Load //Argument3: nCount - Number of functions to load //[Arguments Format] //Argument4: Function Address - Function address we want to store //Argument5: Function Name - Name of the function we want //[Repeat Format] // //Returns: FALSE if failure //Returns: TRUE if successful bool GetProcAddresses(HINSTANCE *hLibrary, #ifdef UNICODE //Test to see if we're using wchar_ts or not. LPCWSTR lpszLibrary, INT nCount, ...) #else LPCSTR lpszLibrary, INT nCount, ...) #endif { va_list va; va_start(va, nCount); if ((*hLibrary = LoadLibrary(lpszLibrary)) != NULL) { FARPROC * lpfProcFunction = NULL; #ifdef UNICODE //Test to see if we're using wchar_ts or not. LPCWSTR lpszFuncName = NULL; #else LPSTR lpszFuncName = NULL; #endif INT nIdxCount = 0; while (nIdxCount < nCount) { lpfProcFunction = va_arg(va, FARPROC*); #ifdef UNICODE //Test to see if we're using wchar_ts or not. lpszFuncName = va_arg(va, LPCWSTR); auto string = StringManipulation::wstrtostr(lpszFuncName); #else lpszFuncName = va_arg(va, LPSTR); StringType string(lpszFuncName); #endif if ((*lpfProcFunction = GetProcAddress(*hLibrary, string.c_str())) == NULL) { lpfProcFunction = NULL; return FALSE; } nIdxCount++; } } else { va_end(va); return FALSE; } va_end(va); return TRUE; } // /////////////////////////// /////////////////////////// // //end of GetProcAddress function// // /////////////////////////// /////////////////////////// // // /////////////////////////// /////////////////////////// // //start of CompareByPriority header// // /////////////////////////// /////////////////////////// // bool CompareByPriority(const DllFunction & a, const DllFunction & b); // /////////////////////////// /////////////////////////// // //end of CompareByPriority header// // /////////////////////////// /////////////////////////// // // /////////////////////////// /////////////////////////// // //start of CompareByPriority function// // /////////////////////////// /////////////////////////// // bool CompareByPriority(const DllFunction &a, const DllFunction &b) { return a.Priority < b.Priority; } //and then use std::sort in the header #include <algorithm>: // /////////////////////////// /////////////////////////// // //end of CompareByPriority function// // /////////////////////////// /////////////////////////// // // /////////////////////////// /////////////////////////// // //start of DynamicallyLoadDllFunctionsFromFile header// // /////////////////////////// /////////////////////////// // void DynamicallyLoadDllFunctionsFromFile(StringType &path, StringType &targetextension, StringType &resourcefilename); // /////////////////////////// /////////////////////////// // //end of DynamicallyLoadDllFunctionsFromFile header// // /////////////////////////// /////////////////////////// // // /////////////////////////// /////////////////////////// // //start of DynamicallyLoadDllFunctionsFromFile function// // /////////////////////////// /////////////////////////// // void DynamicallyLoadDllFunctionsFromFile(StringType &path, StringType &targetextension, StringType &resourcefilename) { std::vector<DllFunction> FunctionVector; auto list = StringManipulation::GetListOfFiles(path); for (auto listitem : list) { //get the current files extension auto extension = StringManipulation::GetExtension(listitem); //get the current filename without extension auto basefilename = StringManipulation::GetBaseFilename(listitem); if (extension == targetextension) { if (basefilename == resourcefilename) { //get a vector of lines from the current file auto itempath = StringManipulation::pathAppend(path, listitem); auto lines = StringManipulation::GetLinesFromFile(itempath); if (!lines.empty()) { for (auto line : lines) { DllFunction function; auto count = 0; //get a vector of each "word" in the current line auto splitlines = StringManipulation::split(line, _T(" ")); for (auto splitline : splitlines) { //use a switch statement to assign values based on the position of the number in the line switch (count) { case 0: function.DllName = splitline; break; case 1: function.DllFunctionName = splitline; break; case 2: function.Priority = StringManipulation::StringToInt(splitline); break; } //CString strMessage; //strMessage.Format(_T("Base FileName = %s Extension = %s Line = %s SplitLine = %s"), basefilename.c_str(), extension.c_str(), line.c_str(), splitline.c_str()); //auto pszFileName = _T("File"); //auto msgboxID = MessageBox(NULL, strMessage, pszFileName, MB_OK); count++; } FunctionVector.push_back(function); } } } } } std::sort(FunctionVector.begin(), FunctionVector.end(), CompareByPriority); DllFunctionParams GlobalParams; std::vector< f_funci> functionvect; for (auto function : FunctionVector) { bool succf; f_funci f_funci; HINSTANCE hLib; #ifdef UNICODE //Test to see if we're using wchar_ts or not. if (GetProcAddresses(&hLib, (LPCWSTR)function.DllName.c_str(), 1, #else if (GetProcAddresses(&hLib, (LPCSTR)_T(function.DllName.c_str()), 1, #endif &f_funci, function.DllFunctionName.c_str())) { succf = true; } if (hLib != NULL) if (succf) FreeLibrary(hLib); auto newparams = f_funci(GlobalParams); GlobalParams = newparams; } } // /////////////////////////// /////////////////////////// // //end of DynamicallyLoadDllFunctionsFromFile function// // /////////////////////////// /////////////////////////// // // /////////////////////////// /////////////////////////// // //main entry point start// // /////////////////////////// /////////////////////////// // int main() { StringType resourcefilename = _T("Functions"); //filter only text files StringType targetextension = _T("txt"); StringType subfolder = _T("chooks"); //get out current working directory auto currentpath = StringManipulation::GetCurrentPath(); //get the list of the files in our current working directory auto path = StringManipulation::pathAppend(currentpath, subfolder); MessageBox(NULL, path.c_str(), path.c_str(), MB_OK); DynamicallyLoadDllFunctionsFromFile(path, targetextension, resourcefilename); return 0; } // /////////////////////////// /////////////////////////// // //main entry point end// // /////////////////////////// /////////////////////////// // Dll File : DLLExport.cpp #include <windows.h> #include <atlstr.h> #include <vector> extern "C" struct DllFunctionParams { std::vector<bool>vectorofbools; std::vector<int>vectorofints; std::vector<double>vectorofdoubles; std::vector<HWND>vectorofhwnds; std::vector<CString>vectorofcstrings; std::vector<HINSTANCE>vectorofhinstance; }; extern "C" { __declspec(dllexport) DllFunctionParams funci(DllFunctionParams &paramsin) { if (!paramsin.vectorofcstrings.empty()) { auto pszFileName = _T("File"); auto msgboxID = MessageBox(NULL, paramsin.vectorofcstrings[0], pszFileName, MB_OK); } CString output; output.Format(_T("Output Received")); DllFunctionParams params; params.vectorofcstrings.push_back(output); return params; // ... } }; Then in the folder where your .exe file is create a subfolder called chooks and place a file called Functions.txt Functions.txt contains these 2 lines C:\Users\username\source\repos\Ikommand\Release\chooks\DllExport1.dll funci 1 C:\Users\username\source\repos\Ikommand\Release\chooks\DllExport1.dll funci 2 //parameter 1 -> the function path parameter this Is where the dll file must be && 2 -> the function name parameter && parameter 3 -> the function priority https://github.com/PeterRussellEvans/DllExport https://github.com/PeterRussellEvans/DynamicallyLoadDll I will make an example that is embedded in a chook soon. It will work for both MCBS and UNICODE character set This should allow Dll files to be replaced without restarting Mastercam, which can be a headache when writing chooks..
  12. Peter from S.C.C.C.

    Changing drill speed mid cycle

    Yeah, if you need it, you need it, Imo if u do a small peck like .005 to .01" it should yield a good finish and clear the chips.
  13. Peter from S.C.C.C.

    Changing drill speed mid cycle

    If it is dragging there is a drilling cycle that turns off the spindle at the bottom of the holes.The hollow shape could give you more vibration if you increase your speed too much, so if you are keen on drilling maybe decrease your peck size. If you arent aiming for precision a reamer is overkill.
  14. Hi Karsten, I believe you are looking for: -> the ChainDIRECTION & reverse_chain function : DllImpExp short ChainDIRECTION ( CHAIN * chain, short view_n ) DllImpExp void reverse_chain ( CHAIN * chain) CHAIN *CreateChain(ent &entity, int flip) { CHAIN *chain; short err = alloc_chain(&chain, FALSE /* partial*/); bool result = (err == 0 && chain != nullptr); if (result) { CHAIN_ENT *last_chain_ent = nullptr; short errCode = add_curve_to_chain(&entity, 0, TRUE, 0, chain, &last_chain_ent); if (errCode != CHAIN_OK) // bail out ! { result = false; } if (ChainDIRECTION(chain, 1) == flip)// if our direction == 1 flip the direction { reverse_chain(chain);//flip the direction } } return (result ? chain : nullptr); }

Join us!

eMastercam - your online source for all things Mastercam.

Together, we are the strongest Mastercam community on the web with over 56,000 members, and our online store offers a wide selection of training materials for all applications and skill levels.

Follow us