How can I convert a C++/CLI int %tmp to native C++ int &tmp?
void test(int %tmp)
{
// here I need int &tmp2 for another pure C++ function call
}
Neither of the existing answers properly handle in/out parameters, let alone any advanced use cases.
This should work for all cases where other_func does not keep the reference after it returns:
void test(int %tmp)
{
pin_ptr<int> pinned_tmp = &tmp;
other_func(*pinned_tmp);
}
Just tried this, works fine:
//in the C++ dll
void testFunc( int& n )
{
n = 5;
}
//in the CLI app
[DllImport( "my.dll", EntryPoint = "?exported_name_here",
CallingConvention = CallingConvention::StdCall )]
void TestFunc( int& );
void test( int% tmp )
{
int n;
TestFunc( n );
tmp = n;
}
void your_function(int *);
void your_function2(int &);
void test(int %tmp)
{
int tmp2;
your_function(&tmp2);
your_function2(tmp2);
tmp=tmp2;
}
Related
I am trying to construct a child class object from a base class object. I have tried the below code.
class A
{
public:
A();
A(A&& objectName) = default;
virtual void setint(int i);
virtual void getint();
int var;
};
class B: public A
{
public:
virtual void getint();
B(A&& objectName);
int j= 20;
};
A::A()
{
}
void A::setint(int i)
{
var = i;
}
void A::getint()
{
qDebug()<<"From A Var"<<var;
}
void B::getint()
{
qDebug()<<"From B j"<<j;
qDebug()<<"From B Var"<<var;
}
B::B(A&& objectName): A(std::move(objectName))
{
}
And in my Main.cpp I am doing this
#include <memory>
int main(int argc, char *argv[])
{
A *obj = new A();
obj->setint(10);
obj->getint();
A *obj1 = new B(std::move(*obj));
obj->getint();
obj1->getint();
return 0;
}
The result I get is
From A Var 10
From A Var 10
From B j 20
From B Var 10
My question is why am I getting the value of Var after A *obj1 = new B(std::move(*obj)); this line. I thought the object pointed by obj must have been destructed.
Let me copy paste from this answer: https://stackoverflow.com/a/15663912/512225
std::move doesn't move from the object. It just returns an rvalue reference whose referand is the object, making it possible to move from the object.
Anyway your code is terrible. I hope you know. If you don't, ask for a review.
void testfunc3(){
char* funcname[20];
int n = 0 ;
n = backtrace((void**)funcname,20);
char** p_need_free = (char**)backtrace_symbols((void**)funcname,n);
int i = 0;
for(i=0;i<n;i++){
printf("funcname is : %s\n",p_need_free[i]);
}
free(p_need_free);
}
void testfunc2(){
testfunc3();
}
void testfunc1(){
testfunc2();
}
/** in another file **/
int main(){
testfunc1();
return 0;
}
this project has 2 files , main() takes 1, other functions take
another, the latter file is compiled as a dynamic library.
C# code:
class Hello{
public void helloWorld(char[] chars){
//do something
}
}
C++ code to call C#:
MyCSDLL::Hello* hello;
//init hello, some calls are ok.
char* myCharPtr;
//init with message
HRESULT result = hello->helloWorld(safeArray, (MyCSDLL::_MyRetVal) _retValPtr);
Adapting from How to create and initialize SAFEARRAY of doubles in C++ to pass to C#
void createSafeArray(SAFEARRAY** saData, char* charPtr)
{
char* iterator = charPtr;
SAFEARRAYBOUND Bound;
Bound.lLbound = 0;
Bound.cElements = 10;
*saData = SafeArrayCreate(VT_R8, 1, &Bound);
char HUGEP *pdFreq;
HRESULT hr = SafeArrayAccessData(*saData, (void HUGEP* FAR*)&pdFreq);
if (SUCCEEDED(hr))
{
do {
*pdFreq++ = *iterator;
} while (*iterator++);
}
}
How to call hello->helloWorld()? it is expecting SAFEARRAY*. The current code gives 80131538 error. How to fix it?
C++ Project is not CLR.
Let's suppose the C# code is this:
namespace ClassLibrary1
{
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.AutoDual)]
public class Hello
{
public void helloWorld(char[] chars)
{
...
}
}
}
Then, you can call it with this C/C++ code, for example:
#import "C:\mycode\ClassLibrary1\bin\Debug\classlibrary1.tlb" raw_interfaces_only
using namespace ClassLibrary1;
HRESULT CallHello(wchar_t* charPtr, int count)
{
CComPtr<_Hello> p;
HRESULT hr = p.CoCreateInstance(__uuidof(Hello));
if (FAILED(hr))
return hr;
SAFEARRAY* psa = SafeArrayCreateVector(VT_UI2, 0, count);
if (!psa)
return E_OUTOFMEMORY;
LPVOID pdata;
hr = SafeArrayAccessData(psa, &pdata);
if (SUCCEEDED(hr))
{
CopyMemory(pdata, charPtr, count * 2); // count is the number of chars
SafeArrayUnaccessData(psa);
hr = p->helloWorld(psa);
}
SafeArrayDestroy(psa);
return hr;
}
.NET's char type is unicode, so the binary size is two bytes, the C equivalent is wchar_t (or unsigned short, etc...). So the safearray element type must match that, that's why I used VT_UI2 (VT_R8 that you used is Real of size 8 bytes, so it's equivalent to .NET's double type).
If you really want to use C's char, then you must do some kind of conversion to a 2-byte character.
Also, you can use the SafeArrayCreateVector function which directly allocates a 1-dimension safe array. Don't forget to call cleanup methods.
i'm trying to create a room which has a goldContainer
The goldContainer is defined in a separate .h file.
When i'm trying to compile it says
error C2079: 'room::goldC' uses undefined class 'goldContainer'
The class voor room:
#pragma once
#include <SFML\Graphics.hpp>
#include "screenSettings.h"
#include "floorplanPatch.h"
#include "floorplanPatchContainer.h"
#include "enemyContainer.h"
#include "goldContainer.h"
class goldContainer;
class room{
public:
room(int themenr, floorplanPatchContainer &f);
void draw(sf::RenderWindow &window);
int getStartPoint();
int getEndPoint();
void addFloorplanPatch(int x, int y, int type, floorplanPatch *patch);
bool isSolid(sf::Vector2f position);
void addEnemy();
static const int FLOOR_TEXTURE1 = 0;
static const int FLOOR_TEXTURE2 = 1;
static const int FLOOR_TEXTURE3 = 2;
static const int FLOOR_TEXTURE4 = 3;
static const int WALL = 4;
static const int OBSTACLE = 5;
static const int COSMETIC = 6;
int floorplan[xAs][yAs];
enemyContainer* getEnemyContainer();
void room::addEnemy(int health);
private:
enemyContainer ec;
int startPoint = 1 + rand() % (yAs - 2);
int endPoint = 1 + rand() % (yAs - 2);
sf::RectangleShape rectangle{ sf::Vector2f{ tileSizeX, tileSizeY } };
sf::Texture wall;
sf::Texture obstacle;
sf::Texture floor1;
sf::Texture floor2;
sf::Texture floor3;
sf::Texture floor4;
sf::Texture cosmetic;
void drawBackgroundTile(sf::RenderWindow &window, int i, int x, int y);
goldContainer goldC;
};
it has class goldContainer; on line 8 otherwise it generates error code 2146.
Could someone maybe explain how to solve this error and/or why this occurs.
#pragma once
#include "gold.h"
#include "sound.h"
#include "player.h"
class player;
class room;
class goldContainer{
public:
goldContainer();
~goldContainer();
void checkPickedUp(player &player);
void draw(sf::RenderWindow &window);
void addGold(int amount, sf::Vector2f position, sf::Vector2f size);
void clearAllGold();
private:
std::vector<gold* > goldDrops;
sound goldPickup{ "sounds\\goldPickup.wav" };
};
I think it might be a circular depedency trough:
^->goldContainer->player->roomContainer->room->|
|<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-< v
Let me show you the problem domain:
class Moon;
class Sun
{
void Rotate(Moon);
};
Now, you implement Sun::Rotate, without giving any class declaration (not forward declaration):
void Sun::Rotate(Moon m) // Error C2027
{
}
What you can do:
Ensure that before Sun::Rotate gets into compilation phase, Moon is declared (i.e. known to compiler by now). You need not to implement any method of Moon, just declare.
Example:
class Moon;
class Sun
{
void Rotate(Moon);
};
// Let it come by now
class Moon
{
public:
void PleaseRotate();
};
// Moon is known
void Sun::Rotate(Moon m)
{
m.PleaseRotate(); // It need not to be implemented by now.
}
Note that Moon::PleaseRotate definition would be resolved by linker, and hence its implementation is not needed before Sun::Rotate.
I wrote some multithreading code using Boost thread library. I initialized two threads in the constructor using the placeholder _1 as the argument required by member function fillSample(int num). But this doesn't compile in my Visual Studio 2010. Following is the code:
#include<boost/thread.hpp>
#include<boost/thread/condition.hpp>
#include<boost/bind/placeholders.hpp>
#define SAMPLING_FREQ 250
#define MAX_NUM_SAMPLES 5*60*SAMPLING_FREQ
#define BUFFER_SIZE 8
class ECG
{
private:
int sample[BUFFER_SIZE];
int sampleIdx;
int readIdx, writeIdx;
boost::thread m_ThreadWrite;
boost::thread m_ThreadRead;
boost::mutex m_Mutex;
boost::condition bufferNotFull, bufferNotEmpty;
public:
ECG();
void fillSample(int num); //get sample from the data stream
void processSample(); //process ECG sample, return the last processed
};
ECG::ECG() : readyFlag(false), sampleIdx(0), readIdx(0), writeIdx(0)
{
m_ThreadWrite=boost::thread((boost::bind(&ECG::fillSample, this, _1)));
m_ThreadRead=boost::thread((boost::bind(&ECG::processSample, this)));
}
void ECG::fillSample(int num)
{
boost::mutex::scoped_lock lock(m_Mutex);
while( (writeIdx-readIdx)%BUFFER_SIZE == BUFFER_SIZE-1 )
{
bufferNotFull.wait(lock);
}
sample[writeIdx] = num;
writeIdx = (writeIdx+1) % BUFFER_SIZE;
bufferNotEmpty.notify_one();
}
void ECG::processSample()
{
boost::mutex::scoped_lock lock(m_Mutex);
while( readIdx == writeIdx )
{
bufferNotEmpty.wait(lock);
}
sample[readIdx] *= 2;
readIdx = (readIdx+1) % BUFFER_SIZE;
++sampleIdx;
bufferNotFull.notify_one();
}
I already included the placeholders.hpp header file but it still doesn't compile. If I replace the _1 with 0, then it will work. But this will initialize the thread function with 0, which is not what I want. Any ideas on how to make this work?
Move the creation to the initialization list:
m_ThreadWrite(boost::bind(&ECG::fillSample, this, _1)), ...
thread object is not copyable, and your compiler doesn't support its move constructor.