cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
Showing results for 
Search instead for 
Did you mean: 

Community Tip - Need help navigating or using the PTC Community? Contact the community team. X

JLink and Toolkit DLLs

Eike_Hauptmann
13-Aquamarine

JLink and Toolkit DLLs

Hi folks,


I have a Problem with my J-Link Tool. I load in my J-Link Tool a Pro/Toolkit DLL. With following command:


...


Dll loadedDll = session.LoadProToolkitDll("MP_DLL", dllPath+dllName, dllPath, true);


Object retobj = loadedDll.ExecuteFunction(fktName, inputs);


retObj.GetOutputArguments();


...


Everything works fine for 10 till 12 steps and then I've get this Error:


Invalid wide string: failed to convert to multibyte


The failure seems to occure in the ExecuteFunction line.


After this Error my Java UI is closed and I get a return value of -1. But I can't catch these failure. I don't know what I should do ... had anyone an idea ?



First I think it would be a time problem, but there seem to be no time problem (I've build in timeouts with 1 second) no more or less parts would be processed.


I've tested it in Creo 2.0 and Creo Elements 5.0 on 64bit. Other commands works like a charme.


Best regards,


Eike


This thread is inactive and closed by the PTC Community Management Team. If you would like to provide a reply and re-open this thread, please notify the moderator and reference the thread. You may also use "Start a topic" button to ask a new question. Please be sure to include what version of the PTC product you are using so another community member knowledgeable about your version may be able to assist.
7 REPLIES 7

You must have a string input into Java that is passed to the Pro/TOOLKIT dll that is causing the issue. I would isolate the error causing string and then begin debugging from that point. You can attach a Visual Studio session to Pro/ENGINEER and put a breakpoint into your dll code to see how the string is coming into the dll.

Patrick Williams | Engineering Systems | c: 616.947.2110
[cid:image001.jpg@01CDA612.723F8500]


Eike -

I have written a Pro/Toolkit task-based DLL just one time for use in a
JLink application. It was difficult and tedious, so give yourself credit
for getting this far.

> Everything works fine for 10 till 12 steps and then I've get this Error:
>
> Invalid wide string: failed to convert to multibyte
>
> The failure seems to occure in the ExecuteFunction line.

It sounds like your Pro/Toolkit DLL and your JLink application are using
incompatible text string types. Since the error says "Invalid wide
string",
my first suspicion is your DLL's output arguments. Is it attempting to use
8-bit text (based on C type char) instead of 16-bit text (based on wchar_t)
in its output arguments?

Can you share with us the source of the DLL function you are calling?

|+| M a r k |+|

Mark Stallard
Rapid Response Development
information Solutions
Integrated Defense Systems
Raytheon Company




(business)
+1.339.645.6423
(cell)
+1.617.331.5443
(tie line)
224.6423

-



235 Presidential Way
Woburn, MA 01801-1060
www.raytheon.com


Raytheon Sustainability

This message contains information that may be confidential and privileged.
Unless you are the addressee (or authorized to receive mail for the
addressee), you should not use, copy or disclose to anyone this message or
any information contained in this message. If you have received this message
in error, please so advise the sender by reply e-mail and delete this
message. Thank you for your cooperation.









Hi Patrick, Hi Mark,


thanks for your answers so far. My actual Toolkit Code is this. I've looked at the inserting strings from the java side of evil 🙂


INPUTS : 0 : MDL_NAME : d7603_a_233_279_nbr<din7603_a_nbr>
INPUTS : 1 : MDL_TYPE : .prt

INPUTS : 0 : MDL_NAME : d7603_a_243_289_nbr<din7603_a_nbr>
INPUTS : 1 : MDL_TYPE : .prt


The first works the second don't work, but thats not everytime the same that doesn't work, so I think I've got a C Problem in my DLL somewhere.






basic.c


extern "C" PRO_TK_DLL_EXPORT ProError regenSolidMdl (ProArgument* inputs, ProArgument** outputs)
{
ProError ret = PRO_TK_NO_ERROR;
ProName mdlName = L";
ProName mdlType = L";
ProMdl mdl = NULL;
ProArgument argRelationMdlName;
ProValueData dataMdl;
ProArgument** o;

// add the output argument for model name and number of lines
ret = ProArrayAlloc (0, sizeof (ProArgument), 1, (ProArray*)outputs);
if (ret != PRO_TK_NO_ERROR)
return ret;
dataMdl.type = PRO_VALUE_TYPE_WSTRING;
swprintf(argRelationMdlName.label, L"MDL_NAME");
ret = ProArrayObjectAdd( (ProArray*)outputs, -1, 1, &argRelationMdlName );

// reads the input
ret = ProArgumentByLabelGet(inputs, L"MDL_NAME", &dataMdl);
if (ret == PRO_TK_NO_ERROR && (dataMdl.type == PRO_VALUE_TYPE_WSTRING))
{
wcscpy(mdlName, dataMdl.v.w);
}

ret = ProArgumentByLabelGet(inputs, L"MDL_TYPE", &dataMdl);
if (ret == PRO_TK_NO_ERROR && (dataMdl.type == PRO_VALUE_TYPE_WSTRING))
{
wcscpy(mdlType, dataMdl.v.w);
}

// read the model
if (wcslen(mdlName) > 0) {
ProMdlType type = GetMdlType(mdlType);
ret = ProMdlInit(mdlName, type, &mdl);
if (ret != PRO_TK_NO_ERROR)
return PRO_TK_CONTINUE;
}
// run function

ret = ProSolidRegenerate((ProSolid)mdl, PRO_REGEN_NO_FLAGS);

ProValuedataWstringSet(&dataMdl,mdlName);
((*outputs)[0]).value = dataMdl;
return ret;
}



FileUtil.c


/*
* GetMdlType returns the type of model according to the name
* mdlName: name of model
* return: error code
*/
ProMdlType GetMdlType(ProName mdlName) {
ProMdlType type;
wchar_t *ending = mdlName + (wcslen(mdlName)-4);
if (_wcsicmp(ending, L".PRT")==0)
{
type = PRO_MDL_PART;
}
else if (_wcsicmp(ending, L".ASM")==0)
{
type = PRO_MDL_ASSEMBLY;
}
else if (_wcsicmp(ending, L".DRW")==0)
{
type = PRO_MDL_DRAWING;
}
return type;
}







The Problem is that I can't get breakpoints in the DLL because it is loaded from outside. But I think to write a second DLL that loads it from the Toolkit side to load the functions from there.



Best regards,


and thank you in advance,


Eike

Eike,
I would make two suggestions:

First, are you following the memory management rules for arguments in your JLink application?
Memory Management in Task Library Functions
To avoid memory leaks or overwrites, the DLL functions must use proper memory management. The DLL function must:
1. Ensure that the contents of the input ProArgument array are not freed. This is taken care of by the calling application and the Pro/TOOLKIT communications code.
2. Use the ProValuedata*Set() functions to assign values to the output ProArgument array. This allows the calling application to free the output array with ProArgumentProarrayFree().
Second, I would use the TEST_CALL_REPORT macro after every Pro/TOOLKIT function call to determine what function is failing. You can find this library in
TestError.h and TestError.c. This will write the results of each function call to a file which has proved to be invaluable in my coding experience. I highly recommend it.

Patrick Williams | Engineering Systems | c: 616.947.2110
[cid:image001.jpg@01CDA61A.323161B0]


Eike -

I agree with Patrick that you should review the memory management
guidelines
for Task DLLs. Memory management mistakes are a common cause of bugs in C,
and they can be difficult to diagnose.

I have a few comments regarding your code:

1. It looks like, for now, your DLL is simply copying the input
argument
into the output list. I assume that you are still experimenting
with
task DLLs. Please let me know if I'm mistaken.

2. You seem to be using the ProValueData variable dataMdl for both
input
and output argument values. It's easy to make mistakes when you
use
a variable for more than one purpose; I suggest you use separate
variables for input and output arguments.

3. It's a good idea to put the ProArrayAlloc() call for outputs at
the
top of the function, but you shouldn't call ProArrayObjectAdd()
until
you are ready to return from the function.

4. I suggest you keep the task function small, and write to do input,
processing and output in that order.

Below is an adaptation of the task DLL I wrote about 3 years ago. If I
wrote
it again, I would use wchar_t exclusively, like you did.

|+| M a r k |+|

Mark Stallard
Rapid Response Development
information Solutions
Integrated Defense Systems
Raytheon Company




(business)
+1.339.645.6423
(cell)
+1.617.331.5443
(tie line)
224.6423

-



235 Presidential Way
Woburn, MA 01801-1060
www.raytheon.com


Raytheon Sustainability

This message contains information that may be confidential and privileged.
Unless you are the addressee (or authorized to receive mail for the
addressee), you should not use, copy or disclose to anyone this message or
any information contained in this message. If you have received this message
in error, please so advise the sender by reply e-mail and delete this
message. Thank you for your cooperation.

// Test application for determining the selected CAGE code value on
// drawing formats which use symbol overlays.

#include <protoolkit.h>
#include <proarray.h>
#include <prodrawing.h>
#include <promdl.h>
#include <proutil.h>
#include <protoolkitdll.h>
#include <string.h>
#include <wchar.h>
#include <stdio.h>
#include <stdlib.h>

#include "get_cage_code.h"

PRO_TK_DLL_EXPORT ProError task_get_cage_code( ProArgument *, ProArgument
** ) ;
static int get_input_drawing( ProArgument *, ProDrawing * ) ;
static int set_output_arg_wstring( ProArgument **, char *, char * ) ;

// user_initialize() is executed when this DLL is loaded.

int user_initialize()
{
return PRO_TK_NO_ERROR ;
}


// user_terminate() is executed when this DLL is unloaded.

void user_terminate()
{
}


// task_get_cage_code() is a Pro/Toolkit task which determines the CAGE
// code of the active drawing.

ProError task_get_cage_code( // Always returns 1 (ignored anyway)
ProArgument *inputs, // (in) Not used
ProArgument **outputs ) // (out) CAGE code, error message
{
ProDrawing drawing ;
ProMdlType mdl_type ;
char cage_code[ 6 ] ;
char message[ 128 ] ;
char issue[ 128 ] ;
int has_cage ;
ProError error ;

// Allocate output argument list
// Get input argument or, failing that, use active drawing.

error = ProArrayAlloc( 2, sizeof( ProArgument ), 1, ( ProArray * )
outputs ) ;

if ( ! get_input_drawing( inputs, &drawing )) {
error = ProMdlCurrentGet( &drawing ) ;

if ( error ) {
sprintf( message, "Can't get current model: %d", error ) ;
set_output_arg_wstring( outputs, "CageCode", " ) ;
set_output_arg_wstring( outputs, "ErrorMessage", message ) ;
return PRO_TK_BAD_CONTEXT ;
}
}

// Confirm that active model is a drawing.

error = ProMdlTypeGet( drawing, &mdl_type ) ;

if ( error ) {
sprintf( message, "Can't determine current model type: %d",
error ) ;
set_output_arg_wstring( outputs, "CageCode", " ) ;
set_output_arg_wstring( outputs, "ErrorMessage", message ) ;
return PRO_TK_BAD_CONTEXT ;
}

if ( mdl_type != PRO_MDL_DRAWING ) {
sprintf( message, "Current model is not drawing.", error ) ;
set_output_arg_wstring( outputs, "CageCode", " ) ;
set_output_arg_wstring( outputs, "ErrorMessage", message ) ;
return PRO_TK_INVALID_TYPE ;
}

// Extract CAGE code from drawing.

has_cage = get_cage_code( drawing, cage_code, issue ) ;

if ( ! has_cage ) {
sprintf( message, "No CAGE code found: %s", issue ) ;
set_output_arg_wstring( outputs, "CageCode", " ) ;
set_output_arg_wstring( outputs, "ErrorMessage", message ) ;
return PRO_TK_EMPTY ;
}

// Return CAGE code.

set_output_arg_wstring( outputs, "CageCode", cage_code ) ;
set_output_arg_wstring( outputs, "ErrorMessage", " ) ;
return PRO_TK_NO_ERROR ;
}

// get_input_drawing() retrieves the drawing from the input arguments.

int get_input_drawing( // Returns 1 on success, else 0
ProArgument *inputs, // (in) Task input argument list
ProDrawing *p_drawing ) // (out) Handle to drawing
{
ProValueData value_data ;
ProError error ;

// Get name of drawing from input argument

error = ProArgumentByLabelGet( inputs, L"DrawName", &value_data ) ;

if ( error ) {
return 0 ;
}

// Create a ProMdl handle from the drawning name.

error = ProMdlInit( value_data.v.w, PRO_MDL_DRAWING, p_drawing ) ;
return ( error == PRO_TK_NO_ERROR ) ;
}

// set_output_arg_wstring() adds a named argument to the output list.

int set_output_arg_wstring(
ProArgument **outputs, // (mod) Task output argument list
char *name, // (in) 8-bit argument name
char *value ) // (in) 8-bit argument value
{
ProArgument arg ;
ProLine value16 ;
ProError error ;

ProStringToWstring( arg.label, name ) ;
ProStringToWstring( value16, value ) ;
error = ProValuedataWstringSet( &( arg.value ), value16 ) ;

if ( error ) {
return 0 ;
}

error = ProArrayObjectAdd(( ProArray * ) outputs, -1, 1, &arg ) ;
return ( error = PRO_TK_NO_ERROR ) ;
}






You're my hero's!


I've changed the order of the commands and change also the variables and don't reuse them. Now it seems like everything works alright.


I've added also the TEST_CALL_REPORT Functions. Here is my new version of the function that works alright.







extern "C" PRO_TK_DLL_EXPORT ProError regenSolidMdl (ProArgument* inputs, ProArgument** outputs) {
ProError ret = PRO_TK_NO_ERROR;
ProName mdlName = L";
ProName mdlType = L";
ProMdl mdl = NULL;
ProArgument argRelationMdlName;
ProValueData nameMdl;
ProValueData typeMdl;
ProValueData retMdl;
ProArgument** o;

if (ret != PRO_TK_NO_ERROR) return ret;
nameMdl.type = PRO_VALUE_TYPE_WSTRING;

// reads the input
ret = ProArgumentByLabelGet(inputs, L"MDL_NAME", &nameMdl);
TEST_CALL_REPORT ("ProArrayAlloc()", "ProArgumentByLabelGet()", ret, ret!=PRO_TK_NO_ERROR);
if (ret == PRO_TK_NO_ERROR && (nameMdl.type == PRO_VALUE_TYPE_WSTRING))
{
wcscpy(mdlName, nameMdl.v.w);
}

ret = ProArgumentByLabelGet(inputs, L"MDL_TYPE", &typeMdl);
TEST_CALL_REPORT ("ProArrayAlloc()", "ProArgumentByLabelGet()", ret, ret!=PRO_TK_NO_ERROR);
if (ret == PRO_TK_NO_ERROR && (typeMdl.type == PRO_VALUE_TYPE_WSTRING))
{
wcscpy(mdlType, typeMdl.v.w);
}

// read the model
if (wcslen(mdlName) > 0) {
ProMdlType type = GetMdlType(mdlType);
ret = ProMdlInit(mdlName, type, &mdl);
TEST_CALL_REPORT ("ProArrayAlloc()", "ProMdlInit()", ret, ret!=PRO_TK_NO_ERROR);
if (ret != PRO_TK_NO_ERROR)
return PRO_TK_CONTINUE;
}

// run function
if (mdl != NULL) {
ret = ProSolidRegenerate((ProSolid)mdl, PRO_REGEN_NO_FLAGS);
TEST_CALL_REPORT ("ProArrayAlloc()", "ProSolidRegenerate()", ret, ret!=PRO_TK_NO_ERROR);
}

// add the output argument for model name and number of lines
ret = ProArrayAlloc (0, sizeof (ProArgument), 1, (ProArray*)outputs);
TEST_CALL_REPORT ("ProArrayAlloc()", "regenSolidMdl()", ret, ret!=PRO_TK_NO_ERROR);
swprintf(argRelationMdlName.label, L"MDL_NAME");
ret = ProArrayObjectAdd((ProArray*)outputs, -1, 1, &argRelationMdlName );
TEST_CALL_REPORT ("ProArrayAlloc()", "ProArrayObjectAdd()", ret, ret!=PRO_TK_NO_ERROR);
ProValuedataWstringSet(&retMdl,mdlName);
((*outputs)[0]).value = retMdl;
return ret;
}






Best regards,


and many thanks,


Eike

Glad we could help Eike. One more suggestion I would make is to make your call to ProSolidRegenerate a loop with a maximum of 3 calls. Sometimes a single regeneration is not enough. That call can return the value PRO_TK_REGEN_AGAIN and if you don't regenerate it again you can receive erroneous data in subsequent Pro/TOOLKIT or JLink calls.

Function ProSolidRegenerate

Description


Regenerates the specified ProSolid<proobjects_h.html#prosolid>.

Synopsis

#include <prosolid.h<prosolid_h.html>>

ProError<protoolkiterrors_h.html#proerror>

ProSolidRegenerate

(


ProSolid<proobjects_h.html#prosolid> p_handle


/* (In)


The ProSolid<proobjects_h.html#prosolid> to regenerate.


*/


int flags


/* (In)


Bitmask containing one or more of the bit flags PRO_REGEN_*


*/

)

Returns


PRO_TK_NO_ERROR<protoolkiterrors_h.html#pro_tk_no_error>

The function successfully regenerated the ProSolid<proobjects_h.html#prosolid>.

PRO_TK_UNATTACHED_FEATS<protoolkiterrors_h.html#pro_tk_unattached_feats>

Unattached features were detected, but there was no regeneration failure

PRO_TK_REGEN_AGAIN<protoolkiterrors_h.html#pro_tk_regen_again>

The model is too complex to regenerate the first time

PRO_TK_GENERAL_ERROR<protoolkiterrors_h.html#pro_tk_general_error>

Failure in regeneration

PRO_TK_BAD_INPUTS<protoolkiterrors_h.html#pro_tk_bad_inputs>

Incompatible flags used.

PRO_TK_BAD_CONTEXT<protoolkiterrors_h.html#pro_tk_bad_context>

Invalid regen flags and/or combination of regeneration flags if mixed with PRO_REGEN_FORCE_REGEN.<prosolid_h.html#pro_regen_force_regen>




Patrick Williams | Engineering Systems | c: 616.947.2110
[cid:image001.jpg@01CDA6C1.479D6A10]
Top Tags