Community Tip - Visit the PTCooler (the community lounge) to get to know your fellow community members and check out some of Dale's Friday Humor posts! X
Hi all,
I'm using Creo Parametric 7.0.2.
I'm working on trying to use C# p/invoke interop method to call a Creo function from the C++ toolkit.
I have a C++ .exe that will include the Creo async functionality.
It exposes these two functions:
extern "C" __declspec(dllexport) int ConnectToCreo()
{
pfcAsyncConnection_ptr connection = pfcAsyncConnection::Start("C:\\Program Files\\PTC\\Creo 7.0.2.0\\Parametric\\bin\\parametric.exe", NULL);
return 0;
}
extern "C" __declspec(dllexport) int NoCreo()
{
return -1;
}
For the C# side, I created a simple command line app:
using System.Runtime.InteropServices;
namespace CreoInteropPoC;
internal class Program
{
[DllImport("CreoAsync.exe", CallingConvention = CallingConvention.Cdecl)]
public static extern int ConnectToCreo();
[DllImport("CreoAsyncDll.exe")]
private static extern int NoCreo();
static void Main(string[] args)
{
Console.WriteLine(NoCreo());
ConnectToCreo();
Console.ReadKey();
}
}
The C# app calls the function NoCreo and works fine but throws an AccessViolationException when calling ConnectToCreo.
I have also attached a screenshot of the call stack.
Is it possible to use p/invoke to call Creo functions? Can you point me to what I'm doing wrong?
Solved! Go to Solution.
I was wondering about
DllImport("CreoAsyncDll.exe"
Are you sure to use DLL Import by specifying an executable?
I found this, but maybe I‘m wrong.
You have to use the .bat file or you call the exe with the psf file. In your case you don’t have set any env var, and you don’t start the xtop. See the psf file for more details.
Hi RPN,
Thank you for the reply. I took your suggestion and attempted to pass in the .bat file to the Start function. The C++ code now looks like this:
#include <pfcAsyncConnection.h>
extern "C" __declspec(dllexport) int ConnectToCreo()
{
pfcAsyncConnection_ptr connection = pfcAsyncConnection::Start("C:\\Program Files\\PTC\\Creo 7.0.2.0\\Parametric\\bin\\parametric.bat", NULL);
return 0;
}
extern "C" __declspec(dllexport) int NoCreo()
{
return -1;
}
The C# code is the same.
I am still getting the AccessViolationException. I reviewed the .bat file and it calls parametric.exe with my .psf file. I checked the .psf file and it appears to have all the needed environment variables listed.
Any other suggestions?
Try to connect to an existing running Creo process
pfcAsyncConnection::Connect
to localize a problem:
a) in starting Creo
b) in API call
By the way, I think, it is possible to start Creo from C# directly
PS: take a look API documentation chapter "Task Based Application Libraries"
Hello,
I took your suggestion and tried to use the Connect function. I updated the code to be this:
#include <pfcAsyncConnection.h>
extern "C" __declspec(dllexport) int ConnectToCreo()
{
//pfcAsyncConnection_ptr connection = pfcAsyncConnection::Start("C:\\Program Files\\PTC\\Creo 7.0.2.0\\Parametric\\bin\\parametric.bat", NULL);
pfcAsyncConnection_ptr connection = pfcAsyncConnection::Connect(NULL, "", NULL, NULL);
return 0;
}
extern "C" __declspec(dllexport) int NoCreo()
{
return -1;
}
My procedure was to open Creo manually using the .bat file and then run my C# app.
Unfortunately, I'm still getting an AccessViolationException. I have attached a new stack-trace.
Does this provide any more information?
As always in asynchc mode, did you set the PRO_COMM_MSG?
Setting up an Asynchronous Creo Parametric
TOOLKIT Application
For your asynchronous application to communicate with Creo Parametric, you must set the environment variable PRO_COMM_MSG_EXE to the full path of the executable pro_comm_msg.exe , that is, <creo_loadpoint>\ <datecode>\Common Files\<machine>\obj\pro_comm_msg.exe
Hi RPN,
I have already added that environment variable. It is added as a System environment variable. This is its value: C:\Program Files\PTC\Creo 7.0.2.0\Common Files\x86e_win64\obj\pro_comm_msg.exe.
Thank you for the suggestion.
I'm not a C# freak, but I checked the example code
You have
extern "C" __declspec(dllexport) int ConnectToCreo()
And if I map this, I think the Code may looks like
extern "C" ProError ConnectToCreo ()
I'm not sure if you need to export your function, probably not.
I think you have to check the sample code in Common Files\otk\otk_cpp\otk_async_examples
Because the error tells you to have a general memory issue.
Hi RPN,
The reason why I need the __declspec(dllexport) is because I'm exporting this function from the executable. When I take this off I get this error:
System.EntryPointNotFoundException: 'Unable to find an entry point named 'ConnectToCreo' in DLL "Path/To/My/DLL'.' which tells me it cannot find my function.
I'll review the OTK async examples. And thanks for the ideas so far.
I was wondering about
DllImport("CreoAsyncDll.exe"
Are you sure to use DLL Import by specifying an executable?
I found this, but maybe I‘m wrong.
Hi RPN,
I read on another forum that the Creo async calls need to be in a .exe. Bu turns out that advice is wrong.
I made my C++ project into a DLL and can now successfully call the Creo functions from the C# code!
Thanks so much for your help!
Hi,
i think the problem in your first example is;
the "pfcAsyncConnection_ptr connection" object is detroyed after calling the exposed function in the c# part.
Hi ChristianVollme,
Thanks for your reply! But my issue has already been resolved. Please see RPN's accepted answer above.