I have a Windows Form in Visual Studio C++. (CLR)
In the header file, I declare void createThread()
private:
void createThread() {
char buffer[1024];
ZeroMemory(buffer, sizeof(buffer));
while (true) {
recv(connection, buffer, sizeof(buffer), 0);
main.displayMessage(gcnew System::String(buffer));
}
ExitThread(0);
}
Now, I want to call function createThread
CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)createThread, NULL, NULL, NULL)
After that I get this error:
a pointe-to-member is not valid for a managed class
I tried user thread library but not support. How can I fix??
It appears that this function is defined in a managed class. You need to use the managed thread object, not unmanaged CreateThread.
This error exists for two reasons: First, it's a instance method, not a static method, so it would need to be called with an instance of this type, which there's no way to pass to CreateThread. Second, it's a managed object, and its methods do not trivially convert to C-style raw function pointers.
Finally, a note about the language: C++/CLI is meant to act as a way to interface managed code (e.g., C#) with unmanaged C++. It's not intended as a primary development language. If you don't need to link managed and unmanaged code, you may want to consider switching to either C# or C++ for your application.
Related
I have a Modelica external C function that calls a function that is in a .dll.
In the C function in the .dll I would like to make use of the ModelicaError() function. However when
#include ModelicaUtilities.h is included a number of errors occur.
What is the correct method for doing this?
I take it I'll need to link against an existing Dymola .lib, which one? What should DYMOLA_STATIC be defined as?
Or should I be compiling the .dll in such a way that these missing functions will be available after compilation with the model?
Any insight into this would be great, Thanks
From all what I know it is currently not possible in a tool-independent way to have shared objects (DLLs on Win) depending on ModelicaError (or any other functions of ModelicaUtilities). See https://github.com/modelica/ModelicaSpecification/issues/2191 for the open issue on the Modelica Language specification.
To use ModelicaError function in a dll you send the a pointer to the ModelicaError function. To do this from Dymola create a wrapper function that passes the pointer to the ModelicaError function to the dll function. For example MathLibraryWrapper:
#pragma once
#include "MathLibrary.h"
int fibonacci_next_int_wrap()
{
return fibonacci_next_int(&ModelicaError);
}
This calls the fibonacci_next_int function which is in MathLibary.cpp in the dll. This is modified to accept a pointer to the ModelicaError function.
int fibonacci_next_int(void(*mError)(const char *))
{
(*mError)("broken");
return (int)fibonacci_next();
}
If this is run it will immediately crash with "broken".
I am working on refactoring a large amount of code from an unmanaged C++ assembly into a C# assembly. There is currently a mixed-mode assembly going between the two with, of course, a mix of managed and unmanaged code. There is a function I am trying to call in the unmanaged C++ which relies on FILE*s (as defined in stdio.h). This function ties into a much larger process which cannot be refactored into the C# code yet, but which now needs to be called from the managed code.
I have searched but cannot find a definitive answer to what kind of underlying system pointer the System::IO::FileStream class uses. Is this just applied on top of a FILE*? Or is there some other way to convert a FileStream^ to a FILE*? I found FileStream::SafeFileHandle, on which I can call DangerousGetHandle().ToPointer() to get a native void*, but I'm just trying to be certain that if I cast this to FILE* that I'm doing the right thing...?
void Write(FILE *out)
{
Data->Write(out); // huge bulk of code, writing the data
}
virtual void __clrcall Write(System::IO::FileStream ^out)
{
// is this right??
FILE *pout = (FILE*)out->SafeFileHandle->DangerousGetHandle().ToPointer();
Write(pout);
}
You'll need _open_osfhandle followed by _fdopen.
Casting is not magic. Just because the input and types output are right for your situation doesn't mean the values are.
I've inherited a piece of custom test equipment with a control library built in a COM object, and I'm trying to connect it to our Tcl test script library. I can connect to the DLL using TCOM, and do some simple control operations with single int parameters. However, certain features are controlled by passing in a C/C++ struct that contains the control blocks, and attempting to use them in TCOM is giving me an error 0x80020005 {Type mismatch.}. The struct is defined in the .idl file, so it's available to TCOM to use.
The simplest example is a particular call as follows:
C++ .idl file:
struct SourceScaleRange
{
float MinVoltage;
float MaxVoltage;
};
interface IAnalogIn : IDispatch{
...
[id(4), helpstring("method GetAdcScaleRange")] HRESULT GetAdcScaleRange(
[out] struct SourceScaleRange *scaleRange);
...
}
Tcl wrapper:
::tcom::import [file join $::libDir "PulseMeas.tlb"] ::char
set ::characterizer(AnalogIn) [::char::AnalogIn]
set scaleRange ""
set response [$::characterizer(AnalogIn) GetAdcScaleRange scaleRange]
Resulting error:
0x80020005 {Type mismatch.}
while executing
"$::characterizer(AnalogIn) GetAdcScaleRange scaleRange"
(procedure "charGetAdcScaleRange" line 4)
When I dump TCOM's methods, it knows of the name of the struct, at least, but it seems to have dropped the struct keyword. Some introspection code
set ifhandle [::tcom::info interface $::characterizer(AnalogIn)]
puts "methods: [$ifhandle methods]"
returns
methods: ... {4 VOID GetAdcScaleRange {{out {SourceScaleRange *} scaleRange}}} ...
I don't know if this is meaningful or not.
At this point, I'd be happy to get any ideas on where to look next. Is this a known TCOM limitation (undocumented, but known)? Is there a way to pre-process the parameter into an appropriate format using tcom? Do I need to force it into a correctly sized block of memory via binary format by manual construction? Do I need to take the DLL back to the original developer and have him pull out all the struct parameters? (Not likely to happen, in this reality.) Any input is good input.
I want to pass a managed array from VB.NET to a function in a VC++ project. How would I declare my C++ function and how would I use the array when I'm inside it? Specifically, I want to make VB compatible functions like the one below, which is written in plain old C.
void Vcopy(double *A, double *B)
{
int n;
for(n=0;n<3;n++)
{
B[n]=A[n];
}
}
Maybe some kind soul could convert this to something that would play nicer with VB. Thanks!
Can the C++ method be managed, e.g., C++/CLI ?
If so, then:
void Vcopy(array<double> ^A, array<double> ^B)
By the way, the rest of the method should be identical, provided that the size is 3 - otherwise use A->Length and B->Length.
I am trying to use a C# class in a C++-CLI project, but Visual Studio will only let me declare a handle (^) to a C# object in a local scope, just inside a function. The only way I got it working was declaring a global pointer to a handle:
SUTAdapter::Form1^ *ptForm1;
But if then I create an object inside a function and give its address to the global pointer:
SUTAdapter::Form1^ form1;
form1 = gcnew SUTAdapter::Form1();
ptForm1 = &form1;
(*ptForm1)->incCounter(0);
When the function exits and I try to use the incCounter function inside some other C++-CLI function, the object seems gone (debugger says this == null). Is there a way to have a global handle of a C# code in C++-CLI? I guess global handles are forbidden for some reason I don't understand but I am out of ideas and I need this done. Thank you.
edit:
*ptForm1 = gcnew SUTAdapter::Form1();
Gives a null reference exception. Why?
This restriction seems consistent with the other CLR-based languages. C# has no concept of a static, function-scoped variable for example. The lack of such functionality in C++/CLI suggests that is the way the CLR works - static objects must be defined at the class scope.
The CLR is object based, so this is just a case of that object-oriented nature influencing the design of languages that run on top of it.
From an OO view point, I like the C# way better anyway.
Ok thanks for your answers but I finally solved it, I found it googling:
http://bytes.com/groups/net-vc/473036-how-define-global-com-object-vc-8-a
It seems that VS doesn't let global handles or static handles inside functions. I am puzzled about this because sometimes it is necessary to access managed objects globally.
The solution is to declare a "GlobalObjects" class with static handles inside it:
ref class GlobalObjects
{
public:
static SUTAdapter::Form1^ hndForm1;
};
This way I can access the C# form/class globally. The error code of the previoous error is C3145, I am still wondering why does not VS allow the declaration of global handles.
Will Visual Studio let you declare a static handle to a C# object in a local scope?
SUTAdapter::Form1^ theForm() {
static SUTAdapter::Form1^ form1 = gcnew SUTAdapter::Form1();
return form1;
}
*ptForm1 = gcnew SUTAdapter::Form1();
Gives a null reference exception because you are dereferncing a null pointer - it is just like a pointer to any other type in that regard.
I think - and that's without testing it - that the problem you're having is because you're storing a pointer to a local handle, which might confuse the garbage collector a little due to the fact that you're taking a pointer to an automatic object.
Have you tried to replace the above assignment with
*ptForm1 = gcnew SUTAdapter::Form1();
instead of the detour via the local object reference?