Return an Object into a Cell from C++ Addin
Return an Object into a Cell from C++ Addin
Hello,
Lets says I have a class Rectangle whose constructor takes in length and width.
In OpenOffice Cell A1 I want to be able to type in
=Rectangle(10,20)
This should invoke the constructor and return a pointer to an object of type Rectangle.
In Cell A2 I want to able to type in
Area(A1)
This should call the area method of rectangle....
Is this possible??
Saleem
Lets says I have a class Rectangle whose constructor takes in length and width.
In OpenOffice Cell A1 I want to be able to type in
=Rectangle(10,20)
This should invoke the constructor and return a pointer to an object of type Rectangle.
In Cell A2 I want to able to type in
Area(A1)
This should call the area method of rectangle....
Is this possible??
Saleem
OpenOffice 3.4.0
Mac OS X 10.5.8
Mac OS X 10.5.8
- Charlie Young
- Volunteer
- Posts: 1559
- Joined: Fri May 14, 2010 1:07 am
Re: Return an Object into a Cell from C++ Addin??
I doubt it. What address space is A1 supposed to be pointing into? If the pointer is into some memory allocated by the function in A1, that memory will be freed when the function exits. It would seem you could return some long integer which pointed to one of your rectangles while the function was executing, but what might be at that address later is anybody's guess, I would think.saleem145 wrote:Is this possible??
Saleem
Apache OpenOffice 4.1.1
Windows XP
Windows XP
- Charlie Young
- Volunteer
- Posts: 1559
- Joined: Fri May 14, 2010 1:07 am
Re: Return an Object into a Cell from C++ Addin??
Life is full of surprises. Just for kicks, I tried this. I used function names RectPtr and RectArea since Rectangle and Area seemed too generic, but here are the details:Charlie Young wrote:I doubt it. What address space is A1 supposed to be pointing into? If the pointer is into some memory allocated by the function in A1, that memory will be freed when the function exits. It would seem you could return some long integer which pointed to one of your rectangles while the function was executing, but what might be at that address later is anybody's guess, I would think.saleem145 wrote:Is this possible??
Saleem
In the idl (with a bunch of other stuff in this case, since I just added these functions to an old project):
Code: Select all
long RectPtr([in] double x,[in] double y);
double RectArea([in] long RectPtr);
Code: Select all
class CRectangle {
double width, height;
public:
CRectangle (double,double);
double area ();
};
CRectangle::CRectangle (double a, double b) {
width = a;
height = b;
}
double CRectangle::area()
{
return (width*height);
}
Code: Select all
long SAL_CALL OldProjectImpl::RectPtr( double x, double y)
throw (RuntimeException)
{
CRectangle *rect;
rect = new CRectangle(x,y);
return (long) rect;
}
double SAL_CALL OldProjectImpl::RectArea( long RectPtr)
throw (RuntimeException)
{
CRectangle *rect;
rect = (CRectangle *) RectPtr;
return rect->area();
}
If I put in A1
Code: Select all
=RECTPTR(10;20)
and so in A2 I put
Code: Select all
=RECTAREA(A1)
I'll be amazed if this generalizes very well, and I wouldn't be surprised If it fails ignominiously at some point, but it does look like something worth playing around with, at least.
Apache OpenOffice 4.1.1
Windows XP
Windows XP
Re: Return an Object into a Cell from C++ Addin
Two comments --
1. Is it possible to return the pointer tugged away somewhere in the Any Data Structure. I would the cell to display "*" in the cell indicating that is a pointer. But we can hide the pointer value in the datastructure and access it when we want.
2. It would be cool if there were just a way to export the functions into a pluggin without having to write the wrappers, xcus etc...
Saleem
1. Is it possible to return the pointer tugged away somewhere in the Any Data Structure. I would the cell to display "*" in the cell indicating that is a pointer. But we can hide the pointer value in the datastructure and access it when we want.
2. It would be cool if there were just a way to export the functions into a pluggin without having to write the wrappers, xcus etc...
Saleem
OpenOffice 3.4.0
Mac OS X 10.5.8
Mac OS X 10.5.8
Re: Return an Object into a Cell from C++ Addin
One more question -- how would this work on a 64 bit machine -- I set the return type to hyper in the idl file and used sal_Int64 in the .cc. But the cell displays a #VALUE error. I think returning any 64 bit integer forces it to display #VALUE....
Saleem
Saleem
OpenOffice 3.4.0
Mac OS X 10.5.8
Mac OS X 10.5.8
- Charlie Young
- Volunteer
- Posts: 1559
- Joined: Fri May 14, 2010 1:07 am
Re: Return an Object into a Cell from C++ Addin
HYPER is not an allowed return type for an add-in function. The numeric value in the cell is in fact a double, your precision there is limited to 15 places, and I think you need 20 or so for 64 bits. A wild idea is to store the number as a string (maybe hex?), and have the function convert it to a number before using it to access memory.saleem145 wrote:One more question -- how would this work on a 64 bit machine -- I set the return type to hyper in the idl file and used sal_Int64 in the .cc. But the cell displays a #VALUE error. I think returning any 64 bit integer forces it to display #VALUE....
Saleem
The pointer to the data structure is the cell value, so how are you going to access it if it's in the data structure?
Apache OpenOffice 4.1.1
Windows XP
Windows XP
Re: Return an Object into a Cell from C++ Addin
How do we ensure the destructor is called if new objects are created. Instead of feeding in a fixed width and depth, try feeding in rand() so every calculate creates a new object....
Saleem
Saleem
OpenOffice 3.4.0
Mac OS X 10.5.8
Mac OS X 10.5.8
- Charlie Young
- Volunteer
- Posts: 1559
- Joined: Fri May 14, 2010 1:07 am
Re: Return an Object into a Cell from C++ Addin
I tried that, I made about 10,000 rectangles with random dimensions, and never had a problem. Of course, our example so far is not much more than a roundabout way of multiplying two numbers, but you likely have something more ambitious in mind.saleem145 wrote:How do we ensure the destructor is called if new objects are created. Instead of feeding in a fixed width and depth, try feeding in rand() so every calculate creates a new object....
Saleem
I've been playing with the 64 bit problem, using my "wild idea" incorporating hex strings. We just need some handy-dandy utility functions
Code: Select all
OUString Dec2OUHex(sal_uInt64 dec)
{
static sal_Unicode hexdigits[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
OUString hexStr = OUString();
sal_uInt64 Quotient;
int Remainder;
if(dec > 0) {
Quotient = dec;
while(Quotient > 0)
{
Remainder = Quotient % 16;
hexStr += OUString(hexdigits[Remainder]);
Quotient /= 16;
}
} else {
hexStr = OUString(hexdigits[0]);
}
return oureverse(hexStr);
}
OUString oureverse(OUString s)
{
OUString r;
r = OUString();
long i;
for(i = s.getLength() - 1;i >= 0; i--)
{
r += OUString(s[i]);
}
return r;
}
sal_uInt64 Hex2Dec64(OUString hexStr)
{
OUString r = oureverse(hexStr);
sal_uInt64 p,val = 0;
long i,j;
int d;
for(i = 0;i < r.getLength();i++)
{
if(r[i] >= '0' && r[i] <= '9')
d = r[i] - '0';
else
d = r[i] - 'A' + 10;
p = 1;
for(j = 0;j < i;j++)
p *= 16;
val += d * p;
}
return val;
}
Code: Select all
OUString SAL_CALL ClassAddinsImpl::RectPtr( double width, double height)
throw (RuntimeException)
{
CRectangle *rect;
rect = new CRectangle(width,height);
return Dec2OUHex((sal_uInt64) rect);
}
double SAL_CALL ClassAddinsImpl::RectArea( const OUString & RectPtr)
throw (RuntimeException)
{
CRectangle *rect;
sal_uInt64 ptr = Hex2Dec64(RectPtr);
rect = (CRectangle *) ptr;
return rect->area();
}
Something like
Code: Select all
=RECTAREA(100)
Maybe something could (should) be done with try/catch.
A cell may be formatted to show * in place of a string, suppressing numbers altogether, with
Code: Select all
;;;"*"
Apache OpenOffice 4.1.1
Windows XP
Windows XP
Re: Return an Object into a Cell from C++ Addin
Thanks. I am working on the hex idea as well.
Saleem
BTW: it would be great if they extended the Any class to support user defined datatypes as well. And then the destructor would work as well.
Saleem
BTW: it would be great if they extended the Any class to support user defined datatypes as well. And then the destructor would work as well.
OpenOffice 3.4.0
Mac OS X 10.5.8
Mac OS X 10.5.8
- Charlie Young
- Volunteer
- Posts: 1559
- Joined: Fri May 14, 2010 1:07 am
Re: Return an Object into a Cell from C++ Addin
I always hate it when I post code and then realize I did something clunky.
Since we're using powers of 2, let's do bit shifting instead of multiplication and division.
I use isOUxdigit in RectArea, where I also use a catch(...). It seems with vc++ that is about the only way to deal with all the things that might go wrong here, and even at that it requires a special compiler switch (/EHa).
That assumes one doesn't want a rectangle with an area of -1.
It catches
and also
RectPtr just checks for bad_alloc, which hasn't happened to me yet.
Edit:
Hmm, clunky code? Why isn't isOUxdigit just
?????????????
Actually, it's because I quickly adapted it from another program, but that one could use some improvement as well.
Since we're using powers of 2, let's do bit shifting instead of multiplication and division.
Code: Select all
OUString Dec2OUHex(sal_uInt64 dec)
{
static sal_Unicode hexdigits[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
OUString hexStr = OUString();
if(dec > 0) {
while(dec > 0)
{
hexStr += OUString(hexdigits[dec % 16]);
dec >>= 4;
}
} else {
hexStr = OUString(hexdigits[0]);
}
return oureverse(hexStr);
}
OUString oureverse(OUString s)
{
OUString r;
r = OUString();
long i;
for(i = s.getLength() - 1;i >= 0; i--)
{
r += OUString(s[i]);
}
return r;
}
sal_uInt64 Hex2Dec64(OUString hexStr)
{
OUString r = oureverse(hexStr);
sal_uInt64 p,val = 0;
long i;
int d;
for(i = 0;i < r.getLength();i++)
{
if(r[i] >= '0' && r[i] <= '9')
d = r[i] - '0';
else
d = r[i] - 'A' + 10;
p = 1;
p <<= 4*i;
val += d * p;
}
return val;
}
int isOUxdigit(sal_Unicode c)
{
static sal_Unicode hexdigits[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
int d = 0, itsnot = 1;
while(itsnot && d < 16)
{
itsnot = c != hexdigits[d++];
}
return !itsnot;
}
Code: Select all
double SAL_CALL ClassAddinsImpl::RectArea( const OUString & RectPtr)
throw (RuntimeException)
{
long i = 0;
while(i < RectPtr.getLength())
if(!isOUxdigit(RectPtr[i++]))
return -1;
try {
CRectangle *rect;
sal_uInt64 ptr = Hex2Dec64(RectPtr);
rect = (CRectangle *) ptr;
return rect->area();
} catch(...) {
return -1;
}
}
It catches
Code: Select all
=RECTAREA("100")
Code: Select all
=RECTAREA("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")
Code: Select all
OUString SAL_CALL ClassAddinsImpl::RectPtr( double width, double height)
throw (RuntimeException)
{
CRectangle *rect;
try {
rect = new CRectangle(width,height);
return Dec2OUHex((sal_uInt64) rect);
} catch (bad_alloc&) {
return OUString(RTL_CONSTASCII_USTRINGPARAM("Can't allocate rectangle"));
}
}
Hmm, clunky code? Why isn't isOUxdigit just
Code: Select all
int isOUxdigit(sal_Unicode c)
{
return (c >= '0' && c <= '9') || (c >='A' && c <= 'F');
}
Actually, it's because I quickly adapted it from another program, but that one could use some improvement as well.
Apache OpenOffice 4.1.1
Windows XP
Windows XP