Jump to content

Welcome to eMastercam

Register now to participate in the forums, access the download area, buy Mastercam training materials, post processors and more. This message will be removed once you have signed in.

Use your display name or email address to sign in:

Sample C-hook program from Developer's Guide


Recommended Posts

Hi, All.

 

Using VS C++ 2008.

 

I'm testing a sample project "CHookNortify" from Developer's Guide.

Made it by C-hook Wizard first. (If converted old source code to VS 2008, there were more errors!)

When made it as a "do-nothing C-hook", merely displaying a message box, it works fine.

 

Then, I added code for "CHookNortify" copied from Developer's Guide, and compiled.

Seems compiling process is OK, but when linking, I see the following errors.

 

I thought these errors were from VS 2008, so I added "/FORCE:MULTIPLE" in "Command Line" in property pages for Linker.

It compiled and linked, and even made a .dll, but when executing the C-hook, an error message "Failed to initialize COM!"

displayed.

 

------ Build started: Project: CHookNortify, Configuration: Release Win32 ------
Linking...
mfcs90.lib(dllmodul.obj) : error LNK2005: _DllMain@12 already defined in CHookNortify.obj
  Creating library Release\CHookNortify.lib and object Release\CHookNortify.exp
Release\CHookNortify.dll : fatal error LNK1169: one or more multiply defined symbols found
Build log was saved at "file://f:\Mastercam_C-hook_related2\Masa_test04\CHookNortify\Release\BuildLog.htm"
CHookNortify - 2 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

 

How can I correct these errors?

As a matter of fact, I've been struggling for this for two days...

Any advice will be appreciated.

Thank you.

Link to comment
Share on other sites
error LNK2005: _DllMain@12 already defined

In the m_notify function you added,remove this line ->

AFX_MANAGE_STATE(AfxGetStaticModuleState());

CHooks should now be "Extension style" DLLs and that is what the (newer) Wizard creates.

And I'm guessing you copy/pasted in from an older sample code which was not for "Extension style" DLLs.

Link to comment
Share on other sites

Changing an "old" style CHook over to be an Extension style is fairly simple,

as long as you have a sample extension style project, which of course the X5 CHook Wizard creates.

*Do create a basic sample Chook project using the X5 Chook Wizard and you can use that as a guide.*

Say that your “old“ CHook project was named CHookExample.

You would have a CHookExample.h & CHookExample.cpp

You will replace those 2 files with the same “named” files that the (X5) Chook Wizard creates.

The “old” ones define your CHook app as derived from CWinApp, which you don’t want.

In the “old” files…

In the .h you would find something like this -> class ChookExample : public CWinApp

and in the .cpp -> ChookExample:: ChookExample ()

You can easily do a full file search/replace in the “new” CHookExample.cpp to set name to want you want and rename both the .h & .cpp to whatever you wish.

Now do a full project search/replace and delete all of this lines ->

AFX_MANAGE_STATE(AfxGetStaticModuleState());

One last thing is the open the Properties of you project and under C++ , Preprocessor -> change the _USRDLL to be _AFXEXT

And you’ll need to add this line in any of the “exported” functions that may need to access any resources (strings, etc) in your project. (This function is declared in the new CHookExample.h, so you will need to #include that file in your main.cpp

You will want to add this call in your standard exported m_main function, which is usually in main.cpp

// Must call this prior to accessing any Resources in the C-Hook DLL !

ChangeResCl res(GetChookResourceHandle());

 

It may sound like a lot, but after you’ve done it once, you see how simple it really is. :)

Link to comment
Share on other sites

Roger,

 

Hello.

 

I tried it. I used "CHookSample" for a test.

It worked fine, but I need more practice. Feel like I don't get the grip...

 

I printed all files,*.cpp and *.h, both old(as-is from 2006) and new(made from CHook Wizard),

and compared them one by one, (side by side).

The difference was clear at a glance.

 

Since I don't have many 'old' sample programs, except ones from Developer's Guide,

I'd rather make a base, or skeleton, program, then port necessary code from the old program.

 

For a try out, I chose "Thelix.c" from very old Developers Guide,Version 9.0 (Beta2) 2001.

It was 2004, when I started to learn C-hook for the first time. (I couldn't make it,just gave up...)

 

Of course, there were many errors when compiled for the first time, then I tried to eliminate them

as much as I could.

However, these two errors I couldn't get rid of, I looked at C-hook help file, but no luck.

Could you tell me what's wrong with it?

 

Here is the whole code, (main.cpp). Some lines commented out were deleted.

// main.cpp for Masa_helix
// C-Hook code generated by CHookWizard
// (c) Copyright 2011, CNC Software, Inc.
// All rights reserved.
//
#include "stdafx.h"
#include "m_core.h"
#include "m_mastercam.h"
#include "Masa_helix.h"  // GetChookResourceHandle()


static real radius = 1.0;
static real theta0 = 0.0;
static real d_theta = 5.0 * D2R;
static real n_rev = 1.0;
static real dz_per_rev = 0.1;
static real taper_angle = 0.0;
static char TXT_HDR[] = "thelix";
static char prm_header[] = "thelix";

//static char thelix_prm_name[FILENAME_MAX] = "thelix.prm";
static char thelix_prm_name[FILENAME_MAX] = "F:\\Mastercam_C-hook_related2\\Masa_test05\\new_CHookNotify_Projects\\Masa_helix\\thelix.prm";
static boolean params_set = FALSE;


#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


extern "C" __declspec(dllexport) int m_version (int version)
{
int ret = C_H_VERSION;

// This allows the C-Hook to run in any version of Mastercam
// that has the same major version
if ( (version / 100) == (C_H_VERSION / 100) )
	ret = version;

return ret;
}


/* __________ get_defaults __________

Purpose: Read the default values from THELIX.PRM if it exists */

static void get_defaults (void)

   {
   char fname[FILENAME_MAX] = "F:\\Mastercam_C-hook_related2\\Masa_test05\\new_CHookNotify_Projects\\Masa_helix\\thelix.prm";
   FILE *f;

/* First set default values in case the parameter files does not exist */

   rd_param_open (thelix_prm_name, prm_header, params_set, &f);

   rd_param (f, "%lf", 1, &radius);
   rd_param (f, "%lf", 2, &theta0);
   rd_param (f, "%lf", 3, &d_theta);
   rd_param (f, "%lf", 4, &n_rev);
   rd_param (f, "%lf", 5, &dz_per_rev);
   rd_param (f, "%lf", 6, &taper_angle);

   params_set = TRUE;
   FCLOSE (f);
//	::MessageBox (NULL, (LPCTSTR)"File read end", (LPCTSTR)"get_defaults", MB_OK);
}    

/* __________ save_defaults __________

Purpose: Write the default values into THELIX.PRM */

static void save_defaults (void)

   {
   FILE *f;

   params_set = TRUE;

   wr_param_start (thelix_prm_name, prm_header, &f);
   if (f == NULL)
       return;

   wr_param (f, "%lf", 1, radius);
   wr_param (f, "%lf", 2, theta0);
   wr_param (f, "%lf", 3, d_theta);
   wr_param (f, "%lf", 4, n_rev);
   wr_param (f, "%lf", 5, dz_per_rev);
   wr_param (f, "%lf", 6, taper_angle);

   FCLOSE (f);
//	::MessageBox (NULL, (LPCTSTR)"File write end", (LPCTSTR)"save_defaults", MB_OK);

   }    

static void make_thelix (void)
   {
//   boolean succf=false;
   MC_BOOL succf;
   char pt_opt;
   short i=0;
short n_pts=0;
   real x, y, z;
   real theta, a, dz, dr, r, tan_taper_angle;

DB_LIST_ENT_PTR d_ptr;
   //db_ptr_type d_ptr; // --> Now what is it?? 04/16/11 m.

   p_3d helix_center;  // center point in world coordinates
   p_3d *pts;    
   p_3d dum;

/* Read defaults */
   get_defaults ();

/* Get values for number of revolutions, radius, incremental angle,
 pitch and taper angle */

   get_real (TXT_HDR,  &radius, &succf);
   if (!succf)
       return;

   get_angle (TXT_HDR,  &theta0, &succf);
   if (!succf)
       return;
   get_angle (TXT_HDR, &d_theta, &succf);
   if (!succf)
       return;
   get_real (TXT_HDR,  &n_rev, &succf);
   if (!succf)
       return;
   get_real (TXT_HDR, &dz_per_rev, &succf);
   if (!succf)
       return;
   get_angle (TXT_HDR, &taper_angle, &succf);
   if (!succf)
       return;

   while (TRUE)
       {
       cleartextall();
//       write_msg (TXT_HDR, m_11);

       point_proc ("", &pt_opt, helix_center, &succf);

       if (!succf)
           break;

       cleartextall();
//       write_msg (TXT_HDR, m_9);
       tan_taper_angle = sin (taper_angle) / cos (taper_angle);

       n_pts = round (n_rev * TWO_PI / d_theta) + 1;
       if (n_pts > max_n_spline_pts)
           {
//           post_warning (TXT_HDR, m_8);
           return;
           }
       pts = MALLOC (n_pts * sizeof (p_3d));
       if (pts == NULL)
           {
//          post_warning (TXT_HDR, m_10);
           return;
           }

       theta = theta0;
       a = dz_per_rev / TWO_PI;

/* Compute points on the helix and write to the ascii file */

       for (i = 0; i < n_pts; i++)
           {
           dz = a * (theta - theta0);
           dr = tan_taper_angle * dz;
           r = radius + dr;
           x = r * cos (theta);
           y = r * sin (theta);
           z = dz;
           if(constr_view_n <= 1)
               vec_3d (x, y, z, pts[i]);
           else
               {
               vec_3d (x, y, z, dum);
               view_to_world(dum, constr_view_n, pts[i]);
               }

           v_add_3d (pts[i], helix_center, pts[i]);
           theta += d_theta;
           }
       make_spline_from_pts (pts, n_pts, main_color, main_level, 1, dum,
                           1, dum, FALSE, &d_ptr, &succf);
       FREE (pts);
       clean_pt (pt_opt, helix_center);

	}

   save_defaults();

//	::MessageBox (NULL, (LPCTSTR)"function make_thelix end", (LPCTSTR)"make_thelix", MB_OK);

   }


extern "C" __declspec(dllexport) int m_main (int not_used)
{
   // Must call this prior to accessing any Resources in the C-Hook DLL !
ChangeResCl res(GetChookResourceHandle());

make_thelix ();

//	::MessageBox (NULL, (LPCTSTR)"Masa_helix END", (LPCTSTR)"Masa_helix", MB_OK);

return MC_NOERROR;
}

 

Here is the error message from VS C++ 2008.

 

StdAfx.cpp

Masa_helix.cpp

main.cpp

.\main.cpp(157) : error C2065: 'max_n_spline_pts' : undeclared identifier

.\main.cpp(162) : error C2440: '=' : cannot convert from 'void *' to 'p_3d (*)'

Conversion from 'void*' to pointer to non-'void' requires an explicit cast

Build log was saved at "file://f:\Mastercam_C-hook_related2\Masa_test05\new_CHookNotify_Projects\Masa_helix\Release\BuildLog.htm"

Masa_helix - 2 error(s), 0 warning(s)

========== Rebuild All: 0 succeeded, 1 failed, 0 skipped ==========

 

Thanks for your help, appreciated.

Link to comment
Share on other sites
I chose "Thelix.c" from very old Developers Guide,Version 9.0 (Beta2) 200

Yes, that is going way back.

 

X5 CHook SDK

 

It appears that there is now a function to return the 'max_n_spline_pts' information.

In -> interfaces\core\CSplineNodeMgr_ch.h

/**

* @par Purpose:

* Returns the maximum number of spline points that can be stored in the current allocation

*/

DllImpExp short get_max_n_spline_pts();

 

 

//      * ADDED *
//	Need to #include -> CSplineNodeMgr_ch.h
short max_n_spline_pts = get_max_n_spline_pts(); //<= New - Set using the 'get_' function

       n_pts = round (n_rev * TWO_PI / d_theta) + 1;
       if (n_pts > max_n_spline_pts)
           {
//           post_warning (TXT_HDR, m_8);
           return;
           }

//        pts = MALLOC (n_pts * sizeof (p_3d));  <= WAS
         pts = (p_3d *)MALLOC (n_pts, sizeof(p_3d)); //<= New - Cast the pointer returned to the appropriate type	
	  if( pts == (p_3d *)NULL)
//        if (pts == NULL)  <- WAS
           {
//          post_warning (TXT_HDR, m_10);
           return;
           }

 

The answer for the 1st error was found by doing a search on all the the header (.h) files in the SDK for "n_spline_pts".

The answer for the 2nd error was found by doing a Google search on "Using MALLOC".

Link to comment
Share on other sites

Roger,

 

Hello. Thanks for your prompt reply.

 

I modified main.cpp as instructed. Compiled for X5 MU1, (and X4 MU3 for a test, too).

 

(1) Added #include "CSplineNodeMgr_CH.h" -> done.

 

(2) short max_n_spline_pts = get_max_n_spline_pts(); -> done.

 

It was strange, even though I added CSplineNodeMgr_CH.h, an error message

".\main.cpp(122) : error C3861: 'get_max_n_spline_pts': identifier not found" was displayed.

 

So, I changed it to "short max_n_spline_pts = CSplineNodeMgr::get_max_n_spline_pts();", then it was OK.

 

(3) pts = (p_3d *) MALLOC (n_pts, sizeof(p_3d)); -> done.

if( pts == (p_3d *)NULL) -> done.

 

(4) .\main.cpp(174) : warning C4002: too many actual parameters for macro 'MALLOC' was displayed.-> warning.

 

(5) LINK : fatal error LNK1181: cannot open input file 'C:\Program.obj' was displayed.

(F.Y.I. If compiled for X4, this error message was not displayed. It made a .dll, but when executed,

I didn't see any helical curve on screen. -> forget about this for now.)

 

Checked Microsoft Support, and they say:

 

To work around this problem, include the drive name for the Intermediate file folder and for the

Output file folder.

To edit the entries for the IntDir folder or for the OutDir folder, follow these steps:

 

1. On the Project menu, click Properties Pages.

2. In the Properties Pages dialog box, click Configuration Properties.

3. In the General list, type new entries for the Output Directory items and for the Intermediate

Directory items that include the drive names.

 

Currently, my Configuration Properties set to $(ConfigurationName).

How do I have to change this setting to? $(SDK_X5)?

 

 

Sorry, I tried to make my questions organized, but it looks like a mess.

Thanks for your great help, appreciated.

Link to comment
Share on other sites

TJ00_SH,

 

I received your project files.

 

I made one change and rebuilt the project and the result -->

 

1>------ Build started: Project: Masa_helix, Configuration: Release Win32 ------

1>Compiling...

1>StdAfx.cpp

1>Masa_helix.cpp

1>main.cpp

1>Compiling resources...

1>Microsoft ® Windows ® Resource Compiler Version 6.1.6723.1

1>Copyright © Microsoft Corporation. All rights reserved.

1>Linking...

1> Creating library Release\Masa_helix.lib and object Release\Masa_helix.exp

1>Generating code

1>Finished generating code

1>Embedding manifest...

1>Build log was saved at "file://c:\CODE\CustomerSupport\TJ00_SH\Release\BuildLog.htm"

1>Masa_helix - 0 error(s), 0 warning(s)[\b]

========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ========

 

The change made was to correct the C4002 Warning.

This is a good example of actually looking at the warnings the compiler issues.

Sometimes you can ignore them, but sometimes not - Like in this case!

 

I Googled -> C4002 MSDN

And clicked on the 1st result...

Compiler Warning (level 1) C4002

After reading this and then taking another look (always a good idea!) at the MALLOC statement…

MALLOC takes 1 parameter (the "size" to allocate) and I mis-typed in my previous answer and was giving it 2. :(

This is incorrect ->

pts = (p_3d *) MALLOC (n_pts, sizeof(p_3d))

This is correct ->

pts = (p_3d *) MALLOC (n_pts * sizeof(p_3d))

 

Like mentioned above...

I made this one change and the project now builds with 0 Errors and 0 Warnings and even better - it works!

I started X5 and run the DLL and after entering the requested data I end up with a helix on the screen. :)

 

 

Project paths...

You mentioned this error ->

(5) LINK : fatal error LNK1181: cannot open input file 'C:\Program.obj' was displayed.

I did not get this.

It seems it is looking for Program.obj in the root folder of your C: drive.

That is strange!

 

1. On the Project menu, click Properties Pages.

2. In the Properties Pages dialog box, click Configuration Properties.

3. In the General list, type new entries for the Output Directory items and for the Intermediate

Directory items that include the drive names.

 

The Output Directory and Intermediate Directory items are "relative" paths and this is the correct default -> $(ConfigurationName)

*See the attached screen image of the Project Path Macros.

 

As for sending a ZIP of a project to someone.

I couple hints that will make everyone's life simpler. :)

Remove all of the file types that the recipient does not need -->

*.pdb

*.obj

These files can be very large and Visual Studio will recreate them when the project is rebuilt.

Do not include the Debug or Release sub-folders, unless you wish to also sent the actual .DLL that the project created.

Even then you can delete all of the other files in those folders.

 

The result ZIP will be MUCH smaller and easy to email.

The *revised project ZIP I emailed back to you is only 13KB and has every thing you need.

 

*In addition to correcting my mistake on the MALLOC statement,

I altered how the path to the thelix.PRM file is determined in the the PRM read/write functions.

post-1117-0-49274600-1303307208_thumb.png

Link to comment
Share on other sites

Roger,

 

Hello.

 

Good news.

To make it short, VS 2008 compiled/linked and made a *.dll.

Tested, it was a beauty. Thank you very much. I'm happy.

 

Before finish it up, a few things...

 

(1) Linker error ..."C"\Program.obj" --> fixed.

Linker properties, Input, Additional Dependencies -> mastercam.lib mccore.lib mcmill.lib UICtrls.lib

I set to like this: $(SDK_X5)\release\masetercam.lib, blah, blah...

(It was working fine many times, but not this time.)

 

(2) A question.

If I want to display some data, e.g."max_n_spline_pts",in MessageBox, converted to string, is this OK?

I searched on the internet and copied a code snippet,it works, but I'm not sure.

There may be some other way, better way, to do that. Like ToString()?

 

short max_n_spline_pts = CSplineNodeMgr::get_max_n_spline_pts(); // *ADDED*

TCHAR str[255];
sprintf_s(str, (LPCTSTR)"value of max_n_spline_pts = %d", max_n_spline_pts);
::MessageBox (NULL, (LPCTSTR)str, (LPCTSTR)"max_n_spline_pts", MB_OK);

       if (n_pts > max_n_spline_pts)

 

(3) *.prm fle locations are nice, too. I liked it.

 

Well, it was little tough, but good experience for me. I learned a lot.

Again, thanks for your help.

Link to comment
Share on other sites

SDK_X5 is the name of an environment variable and you wrap it like this $(VarNameHere) to tell Visual Studio that it is an environment variable that it should retrieve.

I have this set to the base folder of where the (X5) CHook SDK is loaded, which on my system happens to be -> c:\SDK\X5

Just set SDK_X5 = the the appropriate path on your system.

 

You're not programming with a .NET language, so you don't have ToString()

Your method is fine, but since you are using MFC you can also do it this way ->

 

CString msg;

msg.Format("value of max_n_spline_pts = %i", max_n_spline_pts);

::MessageBox (NULL, msg, (LPCTSTR)"max_n_spline_pts", MB_OK);

Link to comment
Share on other sites

Roger,

 

Hello.

 

Thanks for prompt reply.

Tried and checked your advice using Cstring.

 

For a time being, I will keep go on trying to familiarize C-hook programs.

In fact, I've already found next C-hook project.

 

To me, programming is just like solving a puzzle.

If it's too easy, not much fun.

If it's too difficult, loose interest, or hard to keep motivated.

If a problem is just above my knowledge/skill, then a lot of satisfaction

when solved a problem, and my program works just as expected, makes me addict, sort of...

 

Thanks for your help and valuable advice.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.

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

×
×
  • Create New...