hallo leute!
ich möchte gern eine dll (um auf die Gärete am port eines Computer zuzugreifen )
die Funktionen sollen in C geschrieben werden. Als Beispiel sollen Audiodaten über den Mikrophone ausgelesen und über den Lautsprecher des PCs abgespielt werden.
Ich habe die "Portaudio" benutzt, das Programm funktioniert in Visual Studio, aber wird von Mathcad als .dll nicht erkannt. Mir ist nicht klar was ich da falsch mache, kann mir bitte Jemand ein Tipp geben?
Der C-Code habe ich angehängt.
MfG
Robert
hello people!
I would like to writte a user defined function(.dll function) in C, to access at the port of a computer. For example, audio data is to be readed over the microphone(sound recording) and played back over the speakers of the PC.
I have used the "audio port", it's working as program works in Visual Studio but isn't recognized as .dll Mathcad. Dll. I'm not sure what I'm doing wrong, please can somebody give me a hint?
I've attached the C code.
'Tag Robert,
I suppose you did not forget to copy the .DLL file to the UserEFI directory....
Then:
You need brackets {} around the two if statements so that both are bundled with the
case DLL_PROCESS_ATTACH
introducer.
As it is now, only the first if statement (on the error messages) is included. You want to include the user function creation as well.
Hope this solves your problem.
Viel Glück,
Luc
P.S. I see that you use printf() in your DLL. I wonder where the printed data ends up.
Show the full project. Try to load functions from mcaduser.dll dynamically.
thank you very much
I had some problems and could not read the news.
now I get it all and I will try
I took a quick look at things, and it runs fine for me in mc15. Have you specifically set the linker option to DllEntryPoint? In VS2010, it's found under Configuration Properties->Linker->Advanced If you change from c to c++ and create a default win32 dll, things will automatically be set for you and you can drop the _CRT_INIT as well.
Robert
thank you very much
I try the same
{I posted the reaction below on 27-aug-2013, 05:54, but for some silly reason it is still being moderated... Here's a retry.}
Tag Robert,
I suppose you did not forget to copy the .DLL file to the UserEFI directory....
Then:
You need brackets {} around the two if statements so that both are bundled with the
case DLL_PROCESS_ATTACH
introducer.
As it is now, only the first if statement (on the error messages) is included. You want to include the user function creation as well.
Hope this solves your problem.
Viel Glück,
Luc
P.S. I see that you use printf() in your DLL. I wonder where the printed data ends up.
No, the case statement should be fine without braces. The case statement breaks on failure of the error message table creation. If it's successful, it passes through.
As written, the c project builds and runs just fine with vs2010 provided the dll entry point is explicitly set in the linker options. By fine, I mean that if I put a breakpoint in the function and run the dll from Mathcad 15, the breakpoint in the dll is hit. I don't know if, like c++, using DllMain as the entry point in a c project removes the need to specify everything. My one test on the matter had problems when loading meaning I may have incorrectly handled the C run time initialization.
Robert
Hi Robert,
does the program really execute in your Mathcad?, How did you run it?
It compiles correctly in my VS2010, the dll is created but I don't know how to run it in Mathcad. The settings are just right (DllEntryPoint and linker settings).
I did an example of function for calculating the argument of a complex number and i run it successful, but this case is different because the result is not a number, but must do something in the PC, so it's hard for me to run in the Mathcad environment . how can i do it please?
Robert
Mathcad dlls always return a value. In looking more closely at your code, I see the confusion.
First, here's the Mathcad call I used. dummy := recordndPlay(1)
Second, because I didn't have all the files to create your dll, I made the abbreviated function:
LRESULT record_and_play(COMPLEXSCALAR * const arg, const COMPLEXSCALAR * const zahl
/*COMPLEXARRAY * const soundArray, LPCMCSTRING s*/)
{return 0;}
This function is declared incorrectly but runs fine for the following reason. In order for Mathcad to pass variables to the dll, it needs to know the argument list. That's the point of the FUNCTIONINFO structure. Here's what's going on in you case.
FUNCTIONINFO recordAndPlay =
{
// Funktionsname unter der die Funktion in MathCAD verfügbar sein soll"recordAndPlay",
// Beschreibung der Parameter (für Funktion-Einfügen Diaglogfeld)
"zahl",
// Beschreibung der Funktion (für Funktion-Einfügen Diaglogfeld)
"Die Funktion soll ein Sound aufnehmen, in einem File speicher und wiedergeben.",
// Zeiger zur programmierten Funktion
(LPCFUNCTION)record_and_play,
// Datentyp, denn die Funktion zurückgibtCOMPLEX_SCALAR,
// Anzahl der Argumente, welche die Funktion übernimmt1,
// Datentypen der Argumente{COMPLEX_SCALAR}
};
1. You've told Mathcad to create a function called recordAndPlay.
2. the next 2 items are legacy that Mathcad used to put into the insert->function dialog. Now they need to be put in a file called user_EN.xml if you care about having them show up in the insert function list. I've got an automated program to read dlls and generate that file, but I don't think PTC wants exe code posted.
3. You then tell Mathcad that the dll contains a function called record_and_play that it should call when the Mathcad worksheet calls recordAndPlay.
4. record_and_play takes a first argument of type COMPLEX_SCALAR*. This is the return value to Mathcad.
5. record_and_play takes 1 additional user supplied pointer of type const COMPLEX_SCALAR*
Now the type of pointer and whether it's const are compiler drectives. All Mathcad knows is that record_and_play should look like int record_and_play(void*, void*) with the return value being the error code. Internally, it will read the first void* as the variable coming back to Mathcad and treat it as LPCOMPLEX_SCALAR. The second void* Mathcad will supply to the dll as LPCCOMPLEXSCALAR. Since record_and_play is created above as int record_and_play(void*,void*), it ran fine for my abbreviated declaration. More generally, I think you're looking for something like int record_and_play(LPCOMPLEXARRAY ToMathcad, LPCMCSTRING Arg1FromMathcad, LPCMCSCALAR Arg2FromMathcad) which would fill in the FUNCTIONINFO structure as:
COMPLEX_ARRAY,
2,
{STRING, COMPLEX_SCALAR}
Robert
thank you very much
I will check it now